@@ -4,6 +4,7 @@ final class FLIPScheduler {
44 // NOTE: extend this to support css properties as well - for now it is always the bounding rect stuff
55 private var scheduledAnimations : [ DOM . Node : ScheduledNode ] = [ : ]
66 private var runningAnimations : [ DOM . Node : GeometryAnimation ] = [ : ]
7+ private var absolutePositionOriginals : [ DOM . Node : PreviousStyleValues ] = [ : ]
78 private var firstWindowScrollOffset : ( x: Double , y: Double ) ? = nil
89
910 init ( dom: any DOM . Interactor ) {
@@ -44,11 +45,12 @@ final class FLIPScheduler {
4445
4546 func markAsRemoved( _ node: DOM . Node ) {
4647 scheduledAnimations. removeValue ( forKey: node)
48+ absolutePositionOriginals. removeValue ( forKey: node)
4749 let running = runningAnimations. removeValue ( forKey: node)
4850 running? . cancelAll ( )
4951 }
5052
51- func markAsLeaving( _ node: DOM . Node , isReentering : Bool = false ) {
53+ func markAsLeaving( _ node: DOM . Node ) {
5254 assert ( scheduledAnimations [ node] != nil , " node not scheduled for animation " )
5355
5456 if dom. needsAbsolutePositioning ( node) {
@@ -57,6 +59,14 @@ final class FLIPScheduler {
5759 }
5860 }
5961
62+ func markAsReentering( _ node: DOM . Node ) {
63+ assert ( scheduledAnimations [ node] != nil , " node not scheduled for animation " )
64+
65+ if let style = absolutePositionOriginals. removeValue ( forKey: node) {
66+ scheduledAnimations [ node] ? . layoutAction = . undoMoveAbsolute( style: style)
67+ }
68+ }
69+
6070 func commitScheduledAnimations( context: inout _CommitContext ) {
6171 let scroll = dom. getScrollOffset ( )
6272 let firstWindowScroll = firstWindowScrollOffset ?? ( x: Double ( scroll. x) , y: Double ( scroll. y) )
@@ -82,7 +92,6 @@ final class FLIPScheduler {
8292
8393 for (node, animation) in scheduledAnimations {
8494 // TODO: find a good way to preserve velocities of redirected animations
85- // TODO: preserve previous position if it was absolute
8695 // undo all running animations that are effected
8796 runningAnimations [ node] ? . cancelAll ( )
8897
@@ -91,8 +100,9 @@ final class FLIPScheduler {
91100 continue
92101 case . moveAbsolute( let rect) :
93102 let previousValues = context. dom. fixAbsolutePosition ( node, toRect: rect)
94- // TODO: store previousValues for reversal when animation completes
95- _ = previousValues
103+ absolutePositionOriginals [ node] = previousValues
104+ case . undoMoveAbsolute( let style) :
105+ context. dom. undoFixAbsolutePosition ( node, style: style)
96106 }
97107 }
98108 }
@@ -159,6 +169,7 @@ private extension FLIPScheduler {
159169 enum NodeLayoutAction {
160170 case none
161171 case moveAbsolute( rect: DOM . Rect )
172+ case undoMoveAbsolute( style: PreviousStyleValues )
162173 }
163174
164175 struct PreviousStyleValues {
@@ -316,7 +327,7 @@ extension DOM.Interactor {
316327 func needsAbsolutePositioning( _ node: DOM . Node ) -> Bool {
317328 let computedStyle = makeComputedStyleAccessor ( node)
318329 let position = computedStyle. get ( " position " )
319- return position != " absolute " && position != " fixed "
330+ return !position . utf8Equals ( " absolute " ) && !position . utf8Equals ( " fixed " )
320331 }
321332
322333 func getAbsolutePositionCoordinates( _ node: DOM . Node ) -> DOM . Rect {
@@ -362,4 +373,18 @@ private extension DOM.Interactor {
362373
363374 return previousValues
364375 }
376+
377+ func undoFixAbsolutePosition( _ node: DOM . Node , style: FLIPScheduler . PreviousStyleValues ) {
378+ let stylePosition = makeStyleAccessor ( node, cssName: " position " )
379+ let styleLeft = makeStyleAccessor ( node, cssName: " left " )
380+ let styleTop = makeStyleAccessor ( node, cssName: " top " )
381+ let styleWidth = makeStyleAccessor ( node, cssName: " width " )
382+ let styleHeight = makeStyleAccessor ( node, cssName: " height " )
383+
384+ stylePosition. set ( style. position)
385+ styleLeft. set ( style. left)
386+ styleTop. set ( style. top)
387+ styleWidth. set ( style. width)
388+ styleHeight. set ( style. height)
389+ }
365390}
0 commit comments