@@ -88,6 +88,9 @@ export function animation(element, get_fn, get_params) {
8888 /** @type {import('#client').Animation | undefined } */
8989 var animation ;
9090
91+ /** @type {null | { position: string, width: string, height: string } } */
92+ var original_styles = null ;
93+
9194 item . a ??= {
9295 element,
9396 measure ( ) {
@@ -106,11 +109,43 @@ export function animation(element, get_fn, get_params) {
106109 ) {
107110 const options = get_fn ( ) ( this . element , { from, to } , get_params ?. ( ) ) ;
108111
109- animation = animate ( this . element , options , false , undefined , 1 , ( ) => {
112+ animation = animate ( this . element , options , undefined , 1 , ( ) => {
110113 animation ?. abort ( ) ;
111114 animation = undefined ;
112115 } ) ;
113116 }
117+ } ,
118+ fix ( ) {
119+ var computed_style = getComputedStyle ( element ) ;
120+
121+ if ( computed_style . position !== 'absolute' && computed_style . position !== 'fixed' ) {
122+ var style = /** @type {HTMLElement | SVGElement } */ ( element ) . style ;
123+
124+ original_styles = {
125+ position : style . position ,
126+ width : style . width ,
127+ height : style . height
128+ } ;
129+
130+ style . position = 'absolute' ;
131+ style . width = computed_style . width ;
132+ style . height = computed_style . height ;
133+ var to = element . getBoundingClientRect ( ) ;
134+
135+ if ( from . left !== to . left || from . top !== to . top ) {
136+ var transform = `translate(${ from . left - to . left } px, ${ from . top - to . top } px)` ;
137+ style . transform = style . transform ? `${ style . transform } ${ transform } ` : transform ;
138+ }
139+ }
140+ } ,
141+ unfix ( ) {
142+ if ( original_styles ) {
143+ var style = /** @type {HTMLElement | SVGElement } */ ( element ) . style ;
144+
145+ style . position = original_styles . position ;
146+ style . width = original_styles . width ;
147+ style . height = original_styles . height ;
148+ }
114149 }
115150 } ;
116151
@@ -169,7 +204,7 @@ export function transition(flags, element, get_fn, get_params) {
169204
170205 if ( is_intro ) {
171206 dispatch_event ( element , 'introstart' ) ;
172- intro = animate ( element , get_options ( ) , false , outro , 1 , ( ) => {
207+ intro = animate ( element , get_options ( ) , outro , 1 , ( ) => {
173208 dispatch_event ( element , 'introend' ) ;
174209 intro = current_options = undefined ;
175210 } ) ;
@@ -178,12 +213,12 @@ export function transition(flags, element, get_fn, get_params) {
178213 reset ?. ( ) ;
179214 }
180215 } ,
181- out ( fn , position_absolute = false ) {
216+ out ( fn ) {
182217 if ( is_outro ) {
183218 element . inert = true ;
184219
185220 dispatch_event ( element , 'outrostart' ) ;
186- outro = animate ( element , get_options ( ) , position_absolute , intro , 0 , ( ) => {
221+ outro = animate ( element , get_options ( ) , intro , 0 , ( ) => {
187222 dispatch_event ( element , 'outroend' ) ;
188223 outro = current_options = undefined ;
189224 fn ?. ( ) ;
@@ -229,13 +264,12 @@ export function transition(flags, element, get_fn, get_params) {
229264 * Animates an element, according to the provided configuration
230265 * @param {Element } element
231266 * @param {import('#client').AnimationConfig | ((opts: { direction: 'in' | 'out' }) => import('#client').AnimationConfig) } options
232- * @param {boolean } position_absolute
233267 * @param {import('#client').Animation | undefined } counterpart The corresponding intro/outro to this outro/intro
234268 * @param {number } t2 The target `t` value — `1` for intro, `0` for outro
235269 * @param {(() => void) | undefined } callback
236270 * @returns {import('#client').Animation }
237271 */
238- function animate ( element , options , position_absolute , counterpart , t2 , callback ) {
272+ function animate ( element , options , counterpart , t2 , callback ) {
239273 if ( is_function ( options ) ) {
240274 // In the case of a deferred transition (such as `crossfade`), `option` will be
241275 // a function rather than an `AnimationConfig`. We need to call this function
@@ -245,7 +279,7 @@ function animate(element, options, position_absolute, counterpart, t2, callback)
245279
246280 effect ( ( ) => {
247281 var o = untrack ( ( ) => options ( { direction : t2 === 1 ? 'in' : 'out' } ) ) ;
248- a = animate ( element , o , position_absolute , counterpart , t2 , callback ) ;
282+ a = animate ( element , o , counterpart , t2 , callback ) ;
249283 } ) ;
250284
251285 // ...but we want to do so without using `async`/`await` everywhere, so
@@ -285,9 +319,6 @@ function animate(element, options, position_absolute, counterpart, t2, callback)
285319 /** @type {import('#client').Task } */
286320 var task ;
287321
288- /** @type {null | { position: string, width: string, height: string } } */
289- var original_styles = null ;
290-
291322 if ( css ) {
292323 // WAAPI
293324 var keyframes = [ ] ;
@@ -299,37 +330,6 @@ function animate(element, options, position_absolute, counterpart, t2, callback)
299330 keyframes . push ( css_to_keyframe ( styles ) ) ;
300331 }
301332
302- if ( position_absolute ) {
303- // we take the element out of the flow, so that sibling elements with an `animate:`
304- // directive can transform to the correct position
305- var computed_style = getComputedStyle ( element ) ;
306-
307- if ( computed_style . position !== 'absolute' && computed_style . position !== 'fixed' ) {
308- var style = /** @type {HTMLElement | SVGElement } */ ( element ) . style ;
309-
310- original_styles = {
311- position : style . position ,
312- width : style . width ,
313- height : style . height
314- } ;
315-
316- var rect_a = element . getBoundingClientRect ( ) ;
317- style . position = 'absolute' ;
318- style . width = computed_style . width ;
319- style . height = computed_style . height ;
320- var rect_b = element . getBoundingClientRect ( ) ;
321-
322- if ( rect_a . left !== rect_b . left || rect_a . top !== rect_b . top ) {
323- var transform = `translate(${ rect_a . left - rect_b . left } px, ${ rect_a . top - rect_b . top } px)` ;
324- for ( var keyframe of keyframes ) {
325- keyframe . transform = keyframe . transform
326- ? `${ keyframe . transform } ${ transform } `
327- : transform ;
328- }
329- }
330- }
331- }
332-
333333 animation = element . animate ( keyframes , {
334334 delay,
335335 duration,
@@ -340,6 +340,10 @@ function animate(element, options, position_absolute, counterpart, t2, callback)
340340 animation . finished
341341 . then ( ( ) => {
342342 callback ?. ( ) ;
343+
344+ if ( t2 === 1 ) {
345+ animation . cancel ( ) ;
346+ }
343347 } )
344348 . catch ( ( e ) => {
345349 // Error for DOMException: The user aborted a request. This results in two things:
@@ -380,15 +384,6 @@ function animate(element, options, position_absolute, counterpart, t2, callback)
380384 task ?. abort ( ) ;
381385 } ,
382386 deactivate : ( ) => {
383- if ( original_styles ) {
384- // revert `animate:` position fixing
385- var style = /** @type {HTMLElement | SVGElement } */ ( element ) . style ;
386-
387- style . position = original_styles . position ;
388- style . width = original_styles . width ;
389- style . height = original_styles . height ;
390- }
391-
392387 callback = undefined ;
393388 } ,
394389 reset : ( ) => {
0 commit comments