@@ -146,7 +146,9 @@ export async function tryGsapDragIntercept(
146146 const gsapPos = readGsapPositionFromIframe ( iframe , selector ) ;
147147 if ( ! gsapPos ) return false ;
148148
149- await commitGsapPositionFromDrag ( selection , posAnim , offset , gsapPos , { commitMutation } ) ;
149+ await commitGsapPositionFromDrag ( selection , posAnim , offset , gsapPos , iframe , selector , {
150+ commitMutation,
151+ } ) ;
150152 return true ;
151153}
152154
@@ -171,6 +173,8 @@ async function commitGsapPositionFromDrag(
171173 anim : GsapAnimation ,
172174 studioOffset : { x : number ; y : number } ,
173175 gsapPos : { x : number ; y : number } ,
176+ iframe : HTMLIFrameElement | null ,
177+ selector : string ,
174178 callbacks : GsapDragCommitCallbacks ,
175179) : Promise < void > {
176180 // CSS composition: translate → rotate → transform. The studioOffset is in
@@ -188,24 +192,37 @@ async function commitGsapPositionFromDrag(
188192 const clearOffset = ( ) => clearStudioPathOffset ( selection . element ) ;
189193
190194 if ( anim . keyframes ) {
191- await commitKeyframedPosition ( selection , anim , newX , newY , callbacks , clearOffset ) ;
195+ const runtimeProps = readAllAnimatedProperties ( iframe , selector , anim ) ;
196+ await commitKeyframedPosition (
197+ selection ,
198+ anim ,
199+ { ...runtimeProps , x : newX , y : newY } ,
200+ callbacks ,
201+ clearOffset ,
202+ ) ;
192203 } else if ( anim . method === "from" ) {
193204 await commitFromPosition ( selection , anim , studioOffset , callbacks , clearOffset ) ;
194205 } else if ( anim . method === "fromTo" ) {
195206 await commitFromToPosition ( selection , anim , studioOffset , callbacks , clearOffset ) ;
196207 } else {
197208 // Flat to()/set() — convert to keyframes first so the drag position
198209 // is captured at the current seek time, not just the tween endpoint.
199- await commitFlatViaKeyframes ( selection , anim , newX , newY , callbacks , clearOffset ) ;
210+ const runtimeProps = readAllAnimatedProperties ( iframe , selector , anim ) ;
211+ await commitFlatViaKeyframes (
212+ selection ,
213+ anim ,
214+ { ...runtimeProps , x : newX , y : newY } ,
215+ callbacks ,
216+ clearOffset ,
217+ ) ;
200218 }
201219}
202220
203221// fallow-ignore-next-line complexity
204222async function commitKeyframedPosition (
205223 selection : DomEditSelection ,
206224 anim : GsapAnimation ,
207- newX : number ,
208- newY : number ,
225+ properties : Record < string , number > ,
209226 callbacks : GsapDragCommitCallbacks ,
210227 beforeReload : ( ) => void ,
211228) : Promise < void > {
@@ -217,7 +234,7 @@ async function commitKeyframedPosition(
217234 type : "add-keyframe" ,
218235 animationId : anim . id ,
219236 percentage : pct ,
220- properties : { x : newX , y : newY } ,
237+ properties,
221238 } ,
222239 { label : `Move layer (keyframe ${ pct } %)` , softReload : true , beforeReload } ,
223240 ) ;
@@ -232,8 +249,7 @@ async function commitKeyframedPosition(
232249async function commitFlatViaKeyframes (
233250 selection : DomEditSelection ,
234251 anim : GsapAnimation ,
235- newX : number ,
236- newY : number ,
252+ properties : Record < string , number > ,
237253 callbacks : GsapDragCommitCallbacks ,
238254 beforeReload : ( ) => void ,
239255) : Promise < void > {
@@ -251,7 +267,7 @@ async function commitFlatViaKeyframes(
251267 type : "add-keyframe" ,
252268 animationId : anim . id ,
253269 percentage : pct ,
254- properties : { x : newX , y : newY } ,
270+ properties,
255271 } ,
256272 { label : `Move layer (keyframe ${ pct } %)` , softReload : true , beforeReload } ,
257273 ) ;
@@ -316,6 +332,49 @@ async function commitFromToPosition(
316332 ) ;
317333}
318334
335+ // ── Runtime property reader ───────────────────────────────────────────────
336+
337+ function readAllAnimatedProperties (
338+ iframe : HTMLIFrameElement | null ,
339+ selector : string ,
340+ anim : GsapAnimation ,
341+ ) : Record < string , number > {
342+ const result : Record < string , number > = { } ;
343+ if ( ! iframe ?. contentWindow ) return result ;
344+ let gsap : IframeGsap | undefined ;
345+ try {
346+ gsap = ( iframe . contentWindow as unknown as { gsap ?: IframeGsap } ) . gsap ;
347+ } catch {
348+ return result ;
349+ }
350+ if ( ! gsap ?. getProperty ) return result ;
351+ let doc : Document | null = null ;
352+ try {
353+ doc = iframe . contentDocument ;
354+ } catch {
355+ return result ;
356+ }
357+ const el = doc ?. querySelector ( selector ) ;
358+ if ( ! el ) return result ;
359+
360+ const propKeys = new Set < string > ( ) ;
361+ if ( anim . keyframes ) {
362+ for ( const kf of anim . keyframes . keyframes ) {
363+ for ( const p of Object . keys ( kf . properties ) ) {
364+ if ( typeof kf . properties [ p ] === "number" ) propKeys . add ( p ) ;
365+ }
366+ }
367+ } else {
368+ for ( const p of Object . keys ( anim . properties ) ) propKeys . add ( p ) ;
369+ }
370+
371+ for ( const prop of propKeys ) {
372+ const val = Number ( gsap . getProperty ( el , prop ) ) ;
373+ if ( Number . isFinite ( val ) ) result [ prop ] = Math . round ( val ) ;
374+ }
375+ return result ;
376+ }
377+
319378// ── Resize intercept ──────────────────────────────────────────────────────
320379
321380export async function tryGsapResizeIntercept (
@@ -345,13 +404,21 @@ export async function tryGsapResizeIntercept(
345404 ) ;
346405 }
347406
407+ const selector = selectorForSelection ( selection ) ;
408+ const runtimeProps = selector ? readAllAnimatedProperties ( iframe , selector , anim ) : { } ;
409+ const properties = {
410+ ...runtimeProps ,
411+ width : Math . round ( size . width ) ,
412+ height : Math . round ( size . height ) ,
413+ } ;
414+
348415 await commitMutation (
349416 selection ,
350417 {
351418 type : "add-keyframe" ,
352419 animationId : anim . id ,
353420 percentage : pct ,
354- properties : { width : Math . round ( size . width ) , height : Math . round ( size . height ) } ,
421+ properties,
355422 } ,
356423 { label : `Resize (keyframe ${ pct } %)` , softReload : true } ,
357424 ) ;
@@ -407,13 +474,16 @@ export async function tryGsapRotationIntercept(
407474 ) ;
408475 }
409476
477+ const runtimeProps = readAllAnimatedProperties ( iframe , selector , anim ) ;
478+ const properties = { ...runtimeProps , rotation : newRotation } ;
479+
410480 await commitMutation (
411481 selection ,
412482 {
413483 type : "add-keyframe" ,
414484 animationId : anim . id ,
415485 percentage : pct ,
416- properties : { rotation : newRotation } ,
486+ properties,
417487 } ,
418488 { label : `Rotate (keyframe ${ pct } %)` , softReload : true } ,
419489 ) ;
0 commit comments