svelte icon indicating copy to clipboard operation
svelte copied to clipboard

Svelte 5: Run outro transition on `unmount`

Open typhonrt opened this issue 4 months ago • 2 comments

Describe the problem

With Svelte 3 & 4 using a crafty workaround with code example at the end of this issue it is possible to destroy components after outro transitions are run.

Svelte 3&4 related issue: https://github.com/sveltejs/svelte/issues/4056

Is there any comparable svelte/internal mechanisms accessible in Svelte 5 to achieve the same result? I have not found a corresponding capability yet in upgrading my framework to Svelte 5. This would be a rather debilitating situation without a solution for various use cases required by my framework.

It would be nice if unmount in Svelte could take an options object with { outro: boolean } and return a Promise. IE run outro transition, destroy / unmount component and then resolve the Promise.

This would make the declaration:

/**
 * Unmounts a component that was previously mounted using `mount` or `hydrate`. When `outro` is true outro transitions
 * are run before unmounting.
 */
export async function unmount(component: Record<string, any>, options?: { outro: boolean }): Promise<void>;

// Alternate suggestion given that `unmount` should stay synchronous:

/**
 * Unmounts a component that was previously mounted using `mount` or `hydrate` and run any outro transition.
 */
export async function unmountWithOutro(component: Record<string, any>): Promise<void>;

The Svelte 3 & 4 solution to the problem:

import { check_outros, group_outros, transition_out } from 'svelte/internal';

/**
 * Runs outro transition then destroys Svelte component.
 *
 * Workaround for https://github.com/sveltejs/svelte/issues/4056
 *
 * @param {SvelteComponent}  instance - A Svelte component.
 *
 * @returns {Promise<void>} Promise resolved after outro transition completes and component destroyed.
 */
export async function outroAndDestroy(instance)
{
   return new Promise((resolve) =>
   {
      if (instance.$$.fragment && instance.$$.fragment.o)
      {
         group_outros();
         transition_out(instance.$$.fragment, 0, 0, () =>
         {
            instance.$destroy();
            resolve();
         });
         check_outros();
      }
      else
      {
         instance.$destroy();
         resolve();
      }
   });
}

Describe the proposed solution

Modify unmount to take an options object indicating that the outro transition should run and complete before unmounting returning a Promise. Or provide an alternate unmountWithOutro function.

Importance

i cannot use svelte without it / blocking upgrade to Svelte 5.

typhonrt avatar Oct 21 '24 02:10 typhonrt