From 2ddc3c7c21333e5f11945d4ee5a63470faac146f Mon Sep 17 00:00:00 2001 From: Andreas Ehrencrona Date: Fri, 28 Jul 2023 16:29:53 +0200 Subject: [PATCH] Flag for whether to run outro transitions on $destroy --- .../02-client-side-component-api.md | 5 ++++- .../svelte/src/runtime/internal/Component.js | 22 ++++++++++++++----- .../samples/transition-js-destroy/_config.js | 15 +++++++++++++ .../samples/transition-js-destroy/main.svelte | 14 ++++++++++++ 4 files changed, 50 insertions(+), 6 deletions(-) create mode 100644 packages/svelte/test/runtime/samples/transition-js-destroy/_config.js create mode 100644 packages/svelte/test/runtime/samples/transition-js-destroy/main.svelte diff --git a/documentation/docs/04-compiler-and-api/02-client-side-component-api.md b/documentation/docs/04-compiler-and-api/02-client-side-component-api.md index f14fbe3e66..d12021227b 100644 --- a/documentation/docs/04-compiler-and-api/02-client-side-component-api.md +++ b/documentation/docs/04-compiler-and-api/02-client-side-component-api.md @@ -178,17 +178,20 @@ import { SvelteComponent, ComponentConstructorOptions } from 'svelte'; declare global { class Component extends SvelteComponent {} var component: Component; + var run_outro: boolean; } export {} // @filename: index.ts // ---cut--- -component.$destroy(); +component.$destroy(run_outro); ``` Removes a component from the DOM and triggers any `onDestroy` handlers. +If `run_outro` is `true`, any outro transitions will play before the component is destroyed. + ## Component props ```js diff --git a/packages/svelte/src/runtime/internal/Component.js b/packages/svelte/src/runtime/internal/Component.js index bc5b117c2f..09b84ceff0 100644 --- a/packages/svelte/src/runtime/internal/Component.js +++ b/packages/svelte/src/runtime/internal/Component.js @@ -17,7 +17,7 @@ import { element, attr } from './dom.js'; -import { transition_in } from './transitions.js'; +import { check_outros, group_outros, transition_in, transition_out } from './transitions.js'; /** @returns {void} */ export function bind(component, name, callback) { @@ -455,10 +455,22 @@ export class SvelteComponent { */ $$set = undefined; - /** @returns {void} */ - $destroy() { - destroy_component(this, 1); - this.$destroy = noop; + /** + * @param {boolean} [run_outro] + * @returns {void} + */ + $destroy(run_outro) { + if (run_outro && this.$$.fragment && this.$$.fragment.o) { + group_outros(); + transition_out(this.$$.fragment, 0, 0, () => { + destroy_component(this, 1); + this.$destroy = noop; + }); + check_outros(); + } else { + destroy_component(this, 1); + this.$destroy = noop; + } } /** diff --git a/packages/svelte/test/runtime/samples/transition-js-destroy/_config.js b/packages/svelte/test/runtime/samples/transition-js-destroy/_config.js new file mode 100644 index 0000000000..c795b14e0e --- /dev/null +++ b/packages/svelte/test/runtime/samples/transition-js-destroy/_config.js @@ -0,0 +1,15 @@ +export default { + skip_if_ssr: true, + skip_if_hydrate: true, + skip_if_hydrate_from_ssr: true, + test({ assert, component, target, raf }) { + component.$destroy(true); + + return Promise.resolve().then(() => { + const div = target.querySelector('div'); + + raf.tick(50); + assert.equal(div.transitioned, 0.5); + }); + } +}; diff --git a/packages/svelte/test/runtime/samples/transition-js-destroy/main.svelte b/packages/svelte/test/runtime/samples/transition-js-destroy/main.svelte new file mode 100644 index 0000000000..3d3eb655b4 --- /dev/null +++ b/packages/svelte/test/runtime/samples/transition-js-destroy/main.svelte @@ -0,0 +1,14 @@ + + +