feat(studio): GSAP runtime read layer + shared helpers#1557
Merged
miguel-heygen merged 0 commit intoJun 18, 2026
Conversation
Collaborator
Author
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
This was referenced Jun 18, 2026
3365d24 to
74c37f3
Compare
d713c33 to
5e8cf5e
Compare
jrusso1020
approved these changes
Jun 18, 2026
jrusso1020
left a comment
Collaborator
There was a problem hiding this comment.
Approved at 74c37f3a per Rames D Jusso + Via stack review. GSAP runtime read layer + shared helpers — focused, isolated, no concerns.
Reminder: PR body is the unfilled template (stack-wide process flag from Rames D Jusso + Via); please fill in before merge.
5e8cf5e to
f6a0cbb
Compare
74c37f3 to
52dfaa9
Compare
jrusso1020
approved these changes
Jun 18, 2026
jrusso1020
left a comment
Collaborator
There was a problem hiding this comment.
Re-approved at 52dfaa9e post-restack. GSAP runtime read layer unchanged in substance; clean.
52dfaa9 to
06aecb2
Compare
f6a0cbb to
a682a91
Compare
079beeb to
c4717a3
Compare
c4717a3
into
feat/cli-keyframes-command
3 of 4 checks passed
a682a91 to
41ca837
Compare
miguel-heygen
added a commit
that referenced
this pull request
Jun 18, 2026
Consolidates the studio side of the GSAP keyframe/motion-path work into one
PR: runtime read layer + shared helpers, drag/commit/bridge editing infra,
motion-path geometry + commit helpers, on-canvas motion-path overlay, and the
keyframes flag with gesture recording + timeline/selection refinements.
Also fixes "Add keyframe at playhead" for array-form keyframe tweens
(keyframes: [{x,y},…]):
- readElementPosition derived the captured props from anim.properties, which
is empty for array-form keyframes, so the position came back empty and the
add silently no-oped. It now falls back to the union of the keyframe stops'
property keys (then x/y).
- The add site and the toolbar button state computed the playhead percentage
from the element clip range, not the tween range, so keyframes landed at the
wrong percentage. Both now use the tween-relative basis.
- When the playhead is outside the tween range, the button is disabled instead
of silently no-oping (or, post-basis-fix, deleting the boundary keyframe).
Supersedes the separately-reviewed studio PRs #1557, #1558, #1559, #1560, #1561.
miguel-heygen
added a commit
that referenced
this pull request
Jun 18, 2026
Consolidates the studio side of the GSAP keyframe/motion-path work into one
PR: runtime read layer + shared helpers, drag/commit/bridge editing infra,
motion-path geometry + commit helpers, on-canvas motion-path overlay, and the
keyframes flag with gesture recording + timeline/selection refinements.
Also fixes "Add keyframe at playhead" for array-form keyframe tweens
(keyframes: [{x,y},…]):
- readElementPosition derived the captured props from anim.properties, which
is empty for array-form keyframes, so the position came back empty and the
add silently no-oped. It now falls back to the union of the keyframe stops'
property keys (then x/y).
- The add site and the toolbar button state computed the playhead percentage
from the element clip range, not the tween range, so keyframes landed at the
wrong percentage. Both now use the tween-relative basis.
- When the playhead is outside the tween range, "add keyframe at playhead" now
extends the tween to reach it and adds a keyframe there, keeping the existing
keyframes at their absolute times (percentages rescale into the new range),
instead of disabling or no-oping.
Supersedes the separately-reviewed studio PRs #1557, #1558, #1559, #1560, #1561.
miguel-heygen
added a commit
that referenced
this pull request
Jun 18, 2026
Consolidates the studio side of the GSAP keyframe/motion-path work into one
PR: runtime read layer + shared helpers, drag/commit/bridge editing infra,
motion-path geometry + commit helpers, on-canvas motion-path overlay, and the
keyframes flag with gesture recording + timeline/selection refinements.
Also makes "Add keyframe at playhead" do the right thing for every GSAP
animation shape, never disabling or silently no-oping:
- Array-form keyframe tweens (keyframes: [{x,y},…]): readElementPosition now
derives the captured props from the keyframe stops (top-level properties is
empty for array form), and the percentage uses the tween range, not the clip
range — so the add lands at the right spot instead of no-oping.
- Out of the tween range, the action extends the tween to reach the playhead
and adds a hold there, rescaling existing keyframes to keep their absolute
timing (was: disabled / destructive).
- Flat tweens (to/from/fromTo) convert to their natural keyframes, then take
the same add/extend path — so an out-of-range playhead extends them too.
- set() is promoted to a two-stop tween from the set's time to the playhead.
- motionPath/arc tweens add a waypoint at the on-path position (matching
segment, so the curve is preserved) instead of being linearized; outside the
range they extend their duration. A small merge threshold avoids duplicate
waypoints at the path endpoints.
Supersedes the separately-reviewed studio PRs #1557, #1558, #1559, #1560, #1561.
miguel-heygen
added a commit
that referenced
this pull request
Jun 18, 2026
Consolidates the studio side of the GSAP keyframe/motion-path work into one
PR: runtime read layer + shared helpers, drag/commit/bridge editing infra,
motion-path geometry + commit helpers, on-canvas motion-path overlay, and the
keyframes flag with gesture recording + timeline/selection refinements.
Makes "Add keyframe at playhead" do the right thing for every GSAP animation
shape, never disabling or silently no-oping:
- Array-form keyframe tweens (keyframes: [{x,y},…]): readElementPosition now
derives the captured props from the keyframe stops (top-level properties is
empty for array form), and the percentage uses the tween range, not the clip
range — so the add lands at the right spot instead of no-oping.
- Out of the tween range, the action extends the tween to reach the playhead
and adds a hold there, rescaling existing keyframes to keep their absolute
timing (was: disabled / destructive).
- Flat tweens (to/from/fromTo) convert to their natural keyframes, then take
the same add/extend path.
- set() is promoted to a two-stop tween from the set's time to the playhead.
- motionPath/arc tweens add a waypoint at the on-path position (matching
segment, so the curve is preserved) instead of being linearized; outside the
range they extend their duration, with a merge threshold against duplicates.
Also fixes deep-link hydration: on a fresh full-page load the player runtime
isn't ready to honor the first requestSeek, so the one-shot seek latched without
moving the playhead, and the selection hydration (gated on the seek settling)
never ran — a URL with ?t=…&selId=… restored neither. A bounded heartbeat now
retries the seek until the player honors it, then the selection restores.
Supersedes the separately-reviewed studio PRs #1557, #1558, #1559, #1560, #1561.
miguel-heygen
added a commit
that referenced
this pull request
Jun 18, 2026
Consolidates the studio side of the GSAP keyframe/motion-path work into one
PR: runtime read layer + shared helpers, drag/commit/bridge editing infra,
motion-path geometry + commit helpers, on-canvas motion-path overlay, and the
keyframes flag with gesture recording + timeline/selection refinements.
Makes "Add keyframe at playhead" do the right thing for every GSAP animation
shape, never disabling or silently no-oping:
- Array-form keyframe tweens (keyframes: [{x,y},…]): readElementPosition now
derives the captured props from the keyframe stops (top-level properties is
empty for array form), and the percentage uses the tween range, not the clip
range — so the add lands at the right spot instead of no-oping.
- Out of the tween range, the action extends the tween to reach the playhead
and adds a hold there, rescaling existing keyframes to keep their absolute
timing (was: disabled / destructive).
- Flat tweens (to/from/fromTo) convert to their natural keyframes, then take
the same add/extend path.
- set() is promoted to a two-stop tween from the set's time to the playhead.
- motionPath/arc tweens add a waypoint at the on-path position (matching
segment, so the curve is preserved) instead of being linearized; outside the
range they extend their duration, with a merge threshold against duplicates.
Also fixes deep-link hydration. A URL with ?t=…&selId=… restored neither the
playhead nor the selection on a fresh load: useStudioUrlState requests the seek
before the player runtime mounts its requestedSeekTime subscription, so the
request never reached pendingSeekRef, and initializeAdapter (which drained only
pendingSeekRef when the adapter became ready) started at 0 — which also blocked
selection hydration (gated on the seek settling). Fixed at the source:
initializeAdapter now reconciles the store's requestedSeekTime as well, so a seek
requested any time before the adapter is ready lands deterministically.
Supersedes the separately-reviewed studio PRs #1557, #1558, #1559, #1560, #1561.
miguel-heygen
added a commit
that referenced
this pull request
Jun 19, 2026
Consolidates the studio side of the GSAP keyframe/motion-path work into one
PR: runtime read layer + shared helpers, drag/commit/bridge editing infra,
motion-path geometry + commit helpers, on-canvas motion-path overlay, and the
keyframes flag with gesture recording + timeline/selection refinements.
Makes "Add keyframe at playhead" do the right thing for every GSAP animation
shape, never disabling or silently no-oping:
- Array-form keyframe tweens (keyframes: [{x,y},…]): readElementPosition now
derives the captured props from the keyframe stops (top-level properties is
empty for array form), and the percentage uses the tween range, not the clip
range — so the add lands at the right spot instead of no-oping.
- Out of the tween range, the action extends the tween to reach the playhead
and adds a hold there, rescaling existing keyframes to keep their absolute
timing (was: disabled / destructive).
- Flat tweens (to/from/fromTo) convert to their natural keyframes, then take
the same add/extend path.
- set() is promoted to a two-stop tween from the set's time to the playhead.
- motionPath/arc tweens add a waypoint at the on-path position (matching
segment, so the curve is preserved) instead of being linearized; outside the
range they extend their duration, with a merge threshold against duplicates.
Also fixes deep-link hydration. A URL with ?t=…&selId=… restored neither the
playhead nor the selection on a fresh load: useStudioUrlState requests the seek
before the player runtime mounts its requestedSeekTime subscription, so the
request never reached pendingSeekRef, and initializeAdapter (which drained only
pendingSeekRef when the adapter became ready) started at 0 — which also blocked
selection hydration (gated on the seek settling). Fixed at the source:
initializeAdapter now reconciles the store's requestedSeekTime as well, so a seek
requested any time before the adapter is ready lands deterministically.
Supersedes the separately-reviewed studio PRs #1557, #1558, #1559, #1560, #1561.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Stack: GSAP keyframe + motion-path editing — studio runtime read layer (#1553 → #1561).
What
A read layer that reads live GSAP keyframes / motion-paths from the preview iframe runtime, plus shared time helpers, a parsed-animation fetch fallback, and a per-element tween cache.
Why
The static parser can't always resolve keyframes (data-driven loops, computed selectors, fetched values). Reading the live
__timelinesruntime fills the gap; a cold-parse fetch fallback covers the initial-load race where the parse endpoint isn't warm yet.How
gsapRuntimeKeyframes.ts:readRuntimeKeyframes/scanAllRuntimeKeyframesread the live timeline (skipping zero-duration holdsets).gsapShared.ts: tween-relative ↔ clip-relative percentage conversion.useGsapAnimationFetchFallback.ts: retry the parse endpoint on a cold read.useGsapTweenCache.ts: memoize parsed animations per element.Test plan
bun run test(studio) green