fix(studio): a move keeps the route it chose at press through drop and save - #4834
Open
miguel-heygen wants to merge 3 commits into
Open
miguel-heygen wants to merge 3 commits into
miguel-heygen wants to merge 3 commits into
Conversation
Base automatically changed from
fix/studio-move-route-position-channels
to
main
October 1, 2026 05:52
miguel-heygen
force-pushed
the
fix/studio-move-route-once
branch
from
October 1, 2026 06:12
0ad9b0f to
ecc429a
Compare
Edit accuracy: 494 passing here, 494 on the base branchThe gate passes. |
…so the layer goes back
…r, and only a real fold refuses
miguel-heygen
force-pushed
the
fix/studio-move-route-once
branch
from
October 1, 2026 06:50
35f995c to
0da8e10
Compare
miguel-heygen
marked this pull request as ready for review
October 1, 2026 07:26
This branch has not been deployed
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.
Stacked on #4830.
What changes
A move decides whether it moves the layer by its own CSS
translateor through GSAP once, when the gesture starts. The drop and the save then use that decision instead of deciding again.Before, a drag decided the route three times: at press (
createManualOffsetDragMember), when the commit arrived (handleGsapAwarePathOffsetCommitand the group preflight), and in the stager (stageElementOffset). If GSAP took the layer over between those points, the press could draft one way and the save write the other.If GSAP has folded the layer's translate into its own transform since a CSS-route press, the save is refused, because a CSS write at that point would apply the move twice. The user sees "The animation took over this layer's position during the move, so it was not saved." and nothing is written. The refusal also resets GSAP's x/y/xPercent/yPercent to 0, which on the CSS route only ever hold the folded draft, and the gesture's own rollback puts the CSS translate back, so the layer returns to where it started. A real rotation or an authored inline transform such as
rotate(45deg) scale(1.5)is kept. Checked in Chrome with GSAP 3.15: the box is back at its start, and still there after a seek.A fold is "GSAP's cached x/y/xPercent/yPercent are non-zero", not merely "GSAP has parsed the transform": a parse with nothing to fold leaves them at 0, and that move saves normally. A group runs the same check in its preflight, so a group with one taken-over member writes no member at all. Since #4830 nothing on the drag path asks GSAP about a layer it doesn't position, so this is a guard, not an expected path.
How
member.plainTranslate) on the commit: single moves throughMoveCommitOptions.plainTranslate, group moves on eachDomEditGroupPathOffsetCommit.handleGsapAwarePathOffsetCommitand the group commit use the carried route. They decide withgsapWritesPositiononly when nothing was carried, which is the panel's and webmcpmoveTo's case.stageElementOffsettakes the route as a required argument and no longer decides on its own.readMoveOffset(el, plainTranslate)) and passes the route to the commit.Open item
Resize and rotate still read GSAP's x/y/rotation off an element GSAP doesn't position: the resize anchor base in
startGesture, the resize anchor member, and the GSAP resize settle. #4805 (resize) and #4802 (rotate) rewrite exactly those lines and are still open. Once they merge, those reads move under this one decision, with a test that resizing a fade-only box leaves its next move on the CSS route.Tests
Each one fails with its piece of the fix reverted:
domEditOverlayStartGesture.test.ts: "drops on the route it chose at press, even if GSAP takes the element over mid-drag".useGsapAwareEditing.test.tsx: "keeps the route a gesture chose at press", for the CSS route on a layer GSAP has since taken over and the GSAP route on a layer that now looks GSAP-free, single and group.useDomGeometryCommit.test.tsx:useGsapAwareEditing.test.tsx: "writes no member when one CSS-route member has been folded since the press".domEditOverlayStartGesture.test.ts: "drops every member on the route it chose at press" (group).useDomEditNudge.test.tsx: "commits an element without GSAP on the CSS route".propertyPanelTransformCommit.test.ts: the panel reads and moves a GSAP-free layer by its translate and passes the route it chose.Before
Main with #4830, a box with
translate: 40px 30pxand a GSAP tween that only fades it, dragged +90/+60 with GSAP made to fold the box's translate into its own x/y partway through (gsap.getProperty(box, "x")). From the fold on, the box is 114.86 px off the pointer, and the save writesgsap.set("#target", { x: 224, y: 156 }), counting the translate twice, so the box ends 273 px from where it was released. White dotted: where it started. Pink dashed and cross: where it was released.After
Same fixture and gesture on this PR's head. Studio shows "The animation took over this layer's position during the move, so it was not saved.", the file is not changed, and the box goes back to where it started (0 px from its start). White dotted: where it started. Pink dashed and cross: where it was released.