From aac78219cc84e24696d2fa809510bc619dd2b93d Mon Sep 17 00:00:00 2001 From: mtrelis Date: Thu, 16 Jan 2020 13:49:00 +0100 Subject: [PATCH 1/5] commit --- package-lock.json | 2 +- src/runtime/internal/transitions.ts | 6 ++++++ src/runtime/transition/index.ts | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 9ee0b53af6..f2cd6b5abb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.17.0", + "version": "3.17.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/src/runtime/internal/transitions.ts b/src/runtime/internal/transitions.ts index ed23d3c1dd..14f2f1faa4 100644 --- a/src/runtime/internal/transitions.ts +++ b/src/runtime/internal/transitions.ts @@ -207,6 +207,12 @@ export function create_out_transition(node: Element & ElementCSSInlineStyle, fn: config = config(); go(); }); + } else if (config && config.then) { + add_render_callback(() => dispatch(node, false, 'start')); + config.then(() => { + dispatch(node, false, 'end'); + if (!--group.r) run_all(group.c); + }); } else { go(); } diff --git a/src/runtime/transition/index.ts b/src/runtime/transition/index.ts index 0a20c81b1f..1b5ef71376 100644 --- a/src/runtime/transition/index.ts +++ b/src/runtime/transition/index.ts @@ -4,6 +4,7 @@ import { assign, is_function } from 'svelte/internal'; type EasingFunction = (t: number) => number; export interface TransitionConfig { + then?: Promise['then']; delay?: number; duration?: number; easing?: EasingFunction; From fe634a8e042584e5b9d132901f3c2d026ba59c06 Mon Sep 17 00:00:00 2001 From: mtrelis Date: Thu, 16 Jan 2020 14:09:17 +0100 Subject: [PATCH 2/5] c --- src/runtime/internal/transitions.ts | 30 ++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/runtime/internal/transitions.ts b/src/runtime/internal/transitions.ts index 14f2f1faa4..a9711c26e7 100644 --- a/src/runtime/internal/transitions.ts +++ b/src/runtime/internal/transitions.ts @@ -159,6 +159,19 @@ export function create_out_transition(node: Element & ElementCSSInlineStyle, fn: group.r += 1; + function started(){ + add_render_callback(() => dispatch(node, false, 'start')); + } + + function ended(){ + dispatch(node, false, 'end'); + if (!--group.r){ + // this will result in `end()` being called, + // so we don't need to clean up here + run_all(group.c); + } + } + function go() { const { delay = 0, @@ -173,20 +186,14 @@ export function create_out_transition(node: Element & ElementCSSInlineStyle, fn: const start_time = now() + delay; const end_time = start_time + duration; - add_render_callback(() => dispatch(node, false, 'start')); + started(); loop(now => { if (running) { if (now >= end_time) { tick(0, 1); - dispatch(node, false, 'end'); - - if (!--group.r) { - // this will result in `end()` being called, - // so we don't need to clean up here - run_all(group.c); - } + ended(); return false; } @@ -208,11 +215,8 @@ export function create_out_transition(node: Element & ElementCSSInlineStyle, fn: go(); }); } else if (config && config.then) { - add_render_callback(() => dispatch(node, false, 'start')); - config.then(() => { - dispatch(node, false, 'end'); - if (!--group.r) run_all(group.c); - }); + started(); + config.then(ended).catch(ended) } else { go(); } From ce101ea026ab1ec2875b205c813d9183bad7d7ba Mon Sep 17 00:00:00 2001 From: mtrelis Date: Thu, 16 Jan 2020 14:42:46 +0100 Subject: [PATCH 3/5] c --- src/runtime/internal/transitions.ts | 9 +++++---- src/runtime/transition/index.ts | 1 - 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/runtime/internal/transitions.ts b/src/runtime/internal/transitions.ts index a9711c26e7..e64cdee814 100644 --- a/src/runtime/internal/transitions.ts +++ b/src/runtime/internal/transitions.ts @@ -68,6 +68,7 @@ export function transition_out(block, local: 0 | 1, detach: 0 | 1, callback) { const null_transition: TransitionConfig = { duration: 0 }; type TransitionFn = (node: Element, params: any) => TransitionConfig; +type PromiseFn = (node: Element, params: any) => Promise export function create_in_transition(node: Element & ElementCSSInlineStyle, fn: TransitionFn, params: any) { let config = fn(node, params); @@ -150,7 +151,7 @@ export function create_in_transition(node: Element & ElementCSSInlineStyle, fn: }; } -export function create_out_transition(node: Element & ElementCSSInlineStyle, fn: TransitionFn, params: any) { +export function create_out_transition(node: Element & ElementCSSInlineStyle, fn: TransitionFn | PromiseFn, params: any) { let config = fn(node, params); let running = true; let animation_name; @@ -179,7 +180,7 @@ export function create_out_transition(node: Element & ElementCSSInlineStyle, fn: easing = linear, tick = noop, css - } = config || null_transition; + } = config as TransitionConfig || null_transition; if (css) animation_name = create_rule(node, 1, 0, duration, delay, easing, css); @@ -214,7 +215,7 @@ export function create_out_transition(node: Element & ElementCSSInlineStyle, fn: config = config(); go(); }); - } else if (config && config.then) { + } else if (config && 'then' in config) { started(); config.then(ended).catch(ended) } else { @@ -223,7 +224,7 @@ export function create_out_transition(node: Element & ElementCSSInlineStyle, fn: return { end(reset) { - if (reset && config.tick) { + if (reset && 'tick' in config) { config.tick(1, 0); } diff --git a/src/runtime/transition/index.ts b/src/runtime/transition/index.ts index 1b5ef71376..0a20c81b1f 100644 --- a/src/runtime/transition/index.ts +++ b/src/runtime/transition/index.ts @@ -4,7 +4,6 @@ import { assign, is_function } from 'svelte/internal'; type EasingFunction = (t: number) => number; export interface TransitionConfig { - then?: Promise['then']; delay?: number; duration?: number; easing?: EasingFunction; From 029030cd27ec476ef8b7ef4f03a266c3ddf257c6 Mon Sep 17 00:00:00 2001 From: mtrelis Date: Thu, 16 Jan 2020 15:14:35 +0100 Subject: [PATCH 4/5] lint --- src/runtime/internal/transitions.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/runtime/internal/transitions.ts b/src/runtime/internal/transitions.ts index e64cdee814..4fa4cce62a 100644 --- a/src/runtime/internal/transitions.ts +++ b/src/runtime/internal/transitions.ts @@ -160,13 +160,13 @@ export function create_out_transition(node: Element & ElementCSSInlineStyle, fn: group.r += 1; - function started(){ + function started() { add_render_callback(() => dispatch(node, false, 'start')); } - function ended(){ + function ended() { dispatch(node, false, 'end'); - if (!--group.r){ + if (!--group.r) { // this will result in `end()` being called, // so we don't need to clean up here run_all(group.c); @@ -217,7 +217,7 @@ export function create_out_transition(node: Element & ElementCSSInlineStyle, fn: }); } else if (config && 'then' in config) { started(); - config.then(ended).catch(ended) + config.then(ended).catch(ended); } else { go(); } From d643ac784947c045b39dacd03802a87797c8a2ac Mon Sep 17 00:00:00 2001 From: mtrelis Date: Sat, 18 Jan 2020 15:16:45 +0100 Subject: [PATCH 5/5] api docs + test --- site/content/docs/02-template-syntax.md | 2 ++ .../samples/transition-js-promise-outro/_config.js | 14 ++++++++++++++ .../transition-js-promise-outro/main.svelte | 14 ++++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 test/runtime/samples/transition-js-promise-outro/_config.js create mode 100644 test/runtime/samples/transition-js-promise-outro/main.svelte diff --git a/site/content/docs/02-template-syntax.md b/site/content/docs/02-template-syntax.md index 0a4ca2ee1a..9112689ca0 100644 --- a/site/content/docs/02-template-syntax.md +++ b/site/content/docs/02-template-syntax.md @@ -979,6 +979,8 @@ Similar to `transition:`, but only applies to elements entering (`in:`) or leavi Unlike with `transition:`, transitions applied with `in:` and `out:` are not bidirectional — an in transition will continue to 'play' alongside the out transition, rather than reversing, if the block is outroed while the transition is in progress. If an out transition is aborted, transitions will restart from scratch. +If an `out:` custom transition function returns a promise instead of a transition object, svelte will simply await its completion before unmounting the node. + ```html {#if visible}
diff --git a/test/runtime/samples/transition-js-promise-outro/_config.js b/test/runtime/samples/transition-js-promise-outro/_config.js new file mode 100644 index 0000000000..eba6971476 --- /dev/null +++ b/test/runtime/samples/transition-js-promise-outro/_config.js @@ -0,0 +1,14 @@ +export default { + props: { + visible: true, + }, + + test({ assert, component, target }) { + component.visible = false; + assert.notEqual(target.querySelector('span'), undefined); + component.resolve(); + setTimeout(() => { + assert.equal(target.querySelector('span'), undefined); + }); + }, +}; diff --git a/test/runtime/samples/transition-js-promise-outro/main.svelte b/test/runtime/samples/transition-js-promise-outro/main.svelte new file mode 100644 index 0000000000..80b6cc6f2d --- /dev/null +++ b/test/runtime/samples/transition-js-promise-outro/main.svelte @@ -0,0 +1,14 @@ + + +{#if visible} + hello +{/if}