diff --git a/src/compile/dom/Block.ts b/src/compile/dom/Block.ts index 4e88d27a18..71d85bba77 100644 --- a/src/compile/dom/Block.ts +++ b/src/compile/dom/Block.ts @@ -5,6 +5,7 @@ import Compiler from '../Compiler'; import { Node } from '../../interfaces'; export interface BlockOptions { + parent?: Block; name: string; compiler?: Compiler; comment?: string; @@ -14,6 +15,7 @@ export interface BlockOptions { } export default class Block { + parent?: Block; compiler: Compiler; name: string; comment?: string; @@ -50,6 +52,7 @@ export default class Block { autofocus: string; constructor(options: BlockOptions) { + this.parent = options.parent; this.compiler = options.compiler; this.name = options.name; this.comment = options.comment; @@ -115,6 +118,15 @@ export default class Block { } } + addIntro() { + this.hasIntroMethod = true; + } + + addOutro() { + this.hasOutroMethod = true; + this.outros += 1; + } + addVariable(name: string, init?: string) { if (this.variables.has(name) && this.variables.get(name) !== init) { throw new Error( diff --git a/src/compile/nodes/Element.ts b/src/compile/nodes/Element.ts index ec166a8130..28d01ae938 100644 --- a/src/compile/nodes/Element.ts +++ b/src/compile/nodes/Element.ts @@ -182,13 +182,14 @@ export default class Element extends Node { if (this.intro) { this.parent.cannotUseInnerHTML(); - this.compiler.target.hasIntroTransitions = block.hasIntroMethod = true; + this.compiler.target.hasIntroTransitions = true; + block.addIntro(); } if (this.outro) { this.parent.cannotUseInnerHTML(); - this.compiler.target.hasOutroTransitions = block.hasOutroMethod = true; - block.outros += 1; + this.compiler.target.hasOutroTransitions = true; + block.addOutro(); } if (this.ref) { diff --git a/src/compile/nodes/IfBlock.ts b/src/compile/nodes/IfBlock.ts index dd6e98a82a..87727e5b9e 100644 --- a/src/compile/nodes/IfBlock.ts +++ b/src/compile/nodes/IfBlock.ts @@ -95,6 +95,11 @@ export default class IfBlock extends Node { attachBlocks(this); + if (compiler.options.nestedTransitions) { + if (hasIntros) block.addIntro(); + if (hasOutros) block.addOutro(); + } + blocks.forEach(block => { block.hasUpdateMethod = dynamic; block.hasIntroMethod = hasIntros; @@ -129,11 +134,23 @@ export default class IfBlock extends Node { if (this.else) { if (hasOutros) { this.buildCompoundWithOutros(block, parentNode, parentNodes, branches, dynamic, vars); + + if (this.compiler.options.nestedTransitions) { + block.builders.outro.addLine( + `${name}.o(#outrocallback);` + ); + } } else { this.buildCompound(block, parentNode, parentNodes, branches, dynamic, vars); } } else { this.buildSimple(block, parentNode, parentNodes, branches[0], dynamic, vars); + + if (hasOutros && this.compiler.options.nestedTransitions) { + block.builders.outro.addLine( + `if (${name}) ${name}.o(#outrocallback);` + ); + } } block.builders.create.addLine(`${if_name}${name}.c();`); diff --git a/src/interfaces.ts b/src/interfaces.ts index 1a5c356404..a30a67a91f 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -67,6 +67,7 @@ export interface CompileOptions { // to remove in v3 skipIntroByDefault?: boolean; + nestedTransitions: boolean; } export interface GenerateOptions { diff --git a/test/runtime/index.js b/test/runtime/index.js index 1ae37afd61..ceed2bfb0f 100644 --- a/test/runtime/index.js +++ b/test/runtime/index.js @@ -73,6 +73,7 @@ describe("runtime", () => { compileOptions.store = !!config.store; compileOptions.immutable = config.immutable; compileOptions.skipIntroByDefault = config.skipIntroByDefault; + compileOptions.nestedTransitions = config.nestedTransitions; Object.keys(require.cache) .filter(x => x.endsWith(".html")) diff --git a/test/runtime/samples/transition-js-nested-if/_config.js b/test/runtime/samples/transition-js-nested-if/_config.js new file mode 100644 index 0000000000..c8f624b2c7 --- /dev/null +++ b/test/runtime/samples/transition-js-nested-if/_config.js @@ -0,0 +1,28 @@ +export default { + skipIntroByDefault: true, + nestedTransitions: true, + + data: { + x: false, + y: true + }, + + test(assert, component, target, window, raf) { + component.set({ x: true }); + + const div = target.querySelector('div'); + assert.equal(div.foo, 0); + + raf.tick(100); + assert.equal(div.foo, 1); + + component.set({ x: false }); + assert.htmlEqual(target.innerHTML, '
'); + + raf.tick(150); + assert.equal(div.foo, 0.5); + + raf.tick(200); + assert.htmlEqual(target.innerHTML, ''); + }, +}; diff --git a/test/runtime/samples/transition-js-nested-if/main.html b/test/runtime/samples/transition-js-nested-if/main.html new file mode 100644 index 0000000000..cd10c9118f --- /dev/null +++ b/test/runtime/samples/transition-js-nested-if/main.html @@ -0,0 +1,20 @@ +{#if x} + {#if y} + + {/if} +{/if} + + \ No newline at end of file