dispatch transition events inside render callback - fixes #2158

pull/2239/head
Richard Harris 7 years ago
parent cdbd0c3c18
commit e3ee808cc1

@ -2,6 +2,7 @@ import { identity as linear, noop, run_all } from './utils.js';
import { loop } from './loop.js'; import { loop } from './loop.js';
import { create_rule, delete_rule } from './style_manager.js'; import { create_rule, delete_rule } from './style_manager.js';
import { custom_event } from './dom.js'; import { custom_event } from './dom.js';
import { add_render_callback } from './scheduler.js';
let promise; let promise;
@ -16,6 +17,10 @@ function wait() {
return promise; return promise;
} }
function dispatch(node, direction, kind) {
node.dispatchEvent(custom_event(`${direction ? 'intro' : 'outro'}${kind}`));
}
let outros; let outros;
export function group_outros() { export function group_outros() {
@ -239,14 +244,14 @@ export function create_bidirectional_transition(node, fn, params, intro) {
if (b) tick(0, 1); if (b) tick(0, 1);
running_program = init(program, duration); running_program = init(program, duration);
node.dispatchEvent(custom_event(`${running_program.b ? 'intro' : 'outro'}start`)); add_render_callback(() => dispatch(node, b, 'start'))
loop(now => { loop(now => {
if (pending_program && now > pending_program.start) { if (pending_program && now > pending_program.start) {
running_program = init(pending_program, duration); running_program = init(pending_program, duration);
pending_program = null; pending_program = null;
node.dispatchEvent(custom_event(`${running_program.b ? 'intro' : 'outro'}start`)); dispatch(node, running_program.b, 'start');
if (css) { if (css) {
clear_animation(); clear_animation();
@ -257,7 +262,7 @@ export function create_bidirectional_transition(node, fn, params, intro) {
if (running_program) { if (running_program) {
if (now >= running_program.end) { if (now >= running_program.end) {
tick(t = running_program.b, 1 - t); tick(t = running_program.b, 1 - t);
node.dispatchEvent(custom_event(`${running_program.b ? 'intro' : 'outro'}end`)); dispatch(node, running_program.b, 'end');
if (!pending_program) { if (!pending_program) {
// we're done // we're done

@ -1,21 +1,51 @@
export default { export default {
props: { props: {
visible: true, visible: false,
things: ['a', 'b', 'c', 'd'] things: ['a', 'b', 'c', 'd']
}, },
intro: true, // intro: true,
html: `
<p>waiting...</p>
`,
async test({ assert, component, target, raf }) {
component.visible = true;
assert.htmlEqual(target.innerHTML, `
<p>introstart</p>
<p>a</p>
<p>b</p>
<p>c</p>
<p>d</p>
`);
test({ assert, component, target, window, raf }) {
raf.tick(50); raf.tick(50);
assert.deepEqual(component.intros.sort(), ['a', 'b', 'c', 'd']); assert.deepEqual(component.intros.sort(), ['a', 'b', 'c', 'd']);
assert.equal(component.intro_count, 4); assert.equal(component.intro_count, 4);
raf.tick(100); await raf.tick(100);
assert.equal(component.intro_count, 0); assert.equal(component.intro_count, 0);
assert.htmlEqual(target.innerHTML, `
<p>introend</p>
<p>a</p>
<p>b</p>
<p>c</p>
<p>d</p>
`);
component.visible = false; component.visible = false;
assert.htmlEqual(target.innerHTML, `
<p>outrostart</p>
<p>a</p>
<p>b</p>
<p>c</p>
<p>d</p>
`);
raf.tick(150); raf.tick(150);
assert.deepEqual(component.outros.sort(), ['a', 'b', 'c', 'd']); assert.deepEqual(component.outros.sort(), ['a', 'b', 'c', 'd']);
assert.equal(component.outro_count, 4); assert.equal(component.outro_count, 4);
@ -24,12 +54,17 @@ export default {
assert.equal(component.outro_count, 0); assert.equal(component.outro_count, 0);
component.visible = true; component.visible = true;
component.$on('intro.start', () => {
throw new Error(`intro.start should fire during set(), not after`);
});
raf.tick(250); await raf.tick(250);
assert.deepEqual(component.intros.sort(), ['a', 'a', 'b', 'b', 'c', 'c', 'd', 'd']); assert.deepEqual(component.intros.sort(), ['a', 'a', 'b', 'b', 'c', 'c', 'd', 'd']);
assert.equal(component.intro_count, 4); assert.equal(component.intro_count, 4);
assert.htmlEqual(target.innerHTML, `
<p>introstart</p>
<p>a</p>
<p>b</p>
<p>c</p>
<p>d</p>
`);
} }
}; };

@ -9,6 +9,8 @@
export let intro_count = 0; export let intro_count = 0;
export let outro_count = 0; export let outro_count = 0;
let status = 'waiting...';
function foo(node, params) { function foo(node, params) {
return { return {
duration: 100, duration: 100,
@ -21,22 +23,28 @@
function introstart(e) { function introstart(e) {
intros.push(e.target.textContent); intros.push(e.target.textContent);
intro_count += 1; intro_count += 1;
status = 'introstart';
} }
function introend(e) { function introend(e) {
intro_count -= 1; intro_count -= 1;
status = 'introend';
} }
function outrostart(e) { function outrostart(e) {
outros.push(e.target.textContent); outros.push(e.target.textContent);
outro_count += 1; outro_count += 1;
status = 'outrostart';
} }
function outroend(e) { function outroend(e) {
outro_count -= 1; outro_count -= 1;
status = 'outroend';
} }
</script> </script>
<p>{status}</p>
{#each things as thing} {#each things as thing}
{#if visible} {#if visible}
<p <p

Loading…
Cancel
Save