Skip to content

Commit 9b18388

Browse files
committed
Adds compiler option "containedTransitions"
Makes transitions only run when the closest non-component block containing them has changed state. Implements #1480. Without the `containedTransitions` compiler option, all transitions are run whenever their element is added/remove from the dom. With `containedTransitions` the transitions are only run when the closest non-component block (e.g. an if-block or each-block) changes state. This means the transitions on the items of an each-block will not run when the each-block first appears on screen, or when it is removed, but they will run when items are added/removed from the each block. In addition, if a whole page fades in with a transition at the page level, the there will not be other transitions occuring inside the page. The transition containers do not include components, since a component is a reusable container and not a state-driven block. Thus, a transition at the root of a component will run when that component is added to the DOM inside an if-block or each-block the same way an element with a transition inside either of those blocks is run. Intro and outro transitions will run unless `intro` or `outro` on the transition object (e.g. next to duration/delay) are set to false. Transition defaults can be set in the root options, including intro and outro.
1 parent 2e4b65a commit 9b18388

File tree

79 files changed

+506
-149
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+506
-149
lines changed

src/compile/dom/Block.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ export default class Block {
241241
properties.addBlock(`m: @noop,`);
242242
} else {
243243
properties.addBlock(deindent`
244-
${dev ? 'm: function mount' : 'm'}(#target, anchor) {
244+
${dev ? 'm: function mount' : 'm'}(#target, anchor${this.compiler.options.nestedTransitions && ', introing'}) {
245245
${this.builders.mount}
246246
},
247247
`);
@@ -281,10 +281,10 @@ export default class Block {
281281
properties.addBlock(`i: @noop,`);
282282
} else {
283283
properties.addBlock(deindent`
284-
${dev ? 'i: function intro' : 'i'}(#target, anchor) {
284+
${dev ? 'i: function intro' : 'i'}(#target, anchor${this.compiler.options.nestedTransitions && ', introing'}) {
285285
if (#current) return;
286286
${this.builders.intro}
287-
this.m(#target, anchor);
287+
this.m(#target, anchor${this.compiler.options.nestedTransitions && ', introing'});
288288
},
289289
`);
290290
}
@@ -293,7 +293,7 @@ export default class Block {
293293
properties.addBlock(`o: @run,`);
294294
} else {
295295
properties.addBlock(deindent`
296-
${dev ? 'o: function outro' : 'o'}(#outrocallback) {
296+
${dev ? 'o: function outro' : 'o'}(#outrocallback${this.compiler.options.nestedTransitions && ', outroing'}) {
297297
if (!#current) return;
298298
299299
${this.outros > 1 && `#outrocallback = @callAfter(#outrocallback, ${this.outros});`}

src/compile/dom/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ export default function dom(
227227
this._fragment.c();
228228
this._fragment.${block.hasIntroMethod ? 'i' : 'm'}(this.shadowRoot, null);
229229
230-
if (options.target) this._mount(options.target, options.anchor);
230+
if (options.target) this._mount(options.target, options.anchor${compiler.options.nestedTransitions && ', 1'});
231231
` : deindent`
232232
if (options.target) {
233233
${compiler.options.hydratable
@@ -239,7 +239,7 @@ export default function dom(
239239
${options.dev &&
240240
`if (options.hydrate) throw new Error("options.hydrate only works if the component was compiled with the \`hydratable: true\` option");`}
241241
this._fragment.c();`}
242-
this._mount(options.target, options.anchor);
242+
this._mount(options.target, options.anchor${compiler.options.nestedTransitions && ', 1'});
243243
244244
${(compiler.hasComponents || target.hasComplexBindings || hasInitHooks || target.hasIntroTransitions) &&
245245
`@flush(this);`}

src/compile/nodes/AwaitBlock.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ export default class AwaitBlock extends Node {
177177
const ${countdown} = @callAfter(#outrocallback, 3);
178178
for (let #i = 0; #i < 3; #i += 1) {
179179
const block = ${info}.blocks[#i];
180-
if (block) block.o(${countdown});
180+
if (block) block.o(${countdown}, 1);
181181
else ${countdown}();
182182
}
183183
`);

src/compile/nodes/Component.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ export default class Component extends Node {
386386

387387
block.builders.mount.addBlock(deindent`
388388
if (${name}) {
389-
${name}._mount(${parentNode || '#target'}, ${parentNode ? 'null' : 'anchor'});
389+
${name}._mount(${parentNode || '#target'}, ${parentNode ? 'null' : 'anchor'}${compiler.options.nestedTransitions && ', introing'});
390390
${this.ref && `#component.refs.${this.ref} = ${name};`}
391391
}
392392
`);
@@ -486,7 +486,7 @@ export default class Component extends Node {
486486
}
487487

488488
block.builders.mount.addLine(
489-
`${name}._mount(${parentNode || '#target'}, ${parentNode ? 'null' : 'anchor'});`
489+
`${name}._mount(${parentNode || '#target'}, ${parentNode ? 'null' : 'anchor'}${compiler.options.nestedTransitions ? ', introing' : ''});`
490490
);
491491

492492
if (updates.length) {
@@ -505,7 +505,7 @@ export default class Component extends Node {
505505

506506
if (this.compiler.options.nestedTransitions) {
507507
block.builders.outro.addLine(
508-
`if (${name}) ${name}._fragment.o(#outrocallback);`
508+
`if (${name}) ${name}._fragment.o(#outrocallback, outroing);`
509509
);
510510
}
511511
}

src/compile/nodes/EachBlock.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ export default class EachBlock extends Node {
203203

204204
block.builders.mount.addBlock(deindent`
205205
if (${each_block_else}) {
206-
${each_block_else}.${mountOrIntro}(${parentNode || '#target'}, null);
206+
${each_block_else}.${mountOrIntro}(${parentNode || '#target'}, null${this.compiler.options.nestedTransitions && ', 1'});
207207
}
208208
`);
209209

@@ -310,12 +310,11 @@ export default class EachBlock extends Node {
310310
}
311311

312312
block.builders.mount.addBlock(deindent`
313-
for (#i = 0; #i < ${blocks}.length; #i += 1) ${blocks}[#i].${mountOrIntro}(${initialMountNode}, ${anchorNode});
313+
for (#i = 0; #i < ${blocks}.length; #i += 1) ${blocks}[#i].${mountOrIntro}(${initialMountNode}, ${anchorNode}${this.compiler.options.nestedTransitions ? ', 1' : ''});
314314
`);
315315

316316
const dynamic = this.block.hasUpdateMethod;
317317

318-
const rects = block.getUniqueName('rects');
319318
const destroy = this.block.hasAnimation
320319
? `@fixAndOutroAndDestroyBlock`
321320
: this.block.hasOutros
@@ -335,7 +334,7 @@ export default class EachBlock extends Node {
335334
const countdown = block.getUniqueName('countdown');
336335
block.builders.outro.addBlock(deindent`
337336
const ${countdown} = @callAfter(#outrocallback, ${blocks}.length);
338-
for (#i = 0; #i < ${blocks}.length; #i += 1) ${blocks}[#i].o(${countdown});
337+
for (#i = 0; #i < ${blocks}.length; #i += 1) ${blocks}[#i].o(${countdown}, 1);
339338
`);
340339
}
341340

@@ -385,7 +384,7 @@ export default class EachBlock extends Node {
385384

386385
block.builders.mount.addBlock(deindent`
387386
for (var #i = 0; #i < ${iterations}.length; #i += 1) {
388-
${iterations}[#i].${mountOrIntro}(${initialMountNode}, ${anchorNode});
387+
${iterations}[#i].${mountOrIntro}(${initialMountNode}, ${anchorNode}${this.compiler.options.nestedTransitions && ', 1'});
389388
}
390389
`);
391390

@@ -397,16 +396,17 @@ export default class EachBlock extends Node {
397396

398397
const outroBlock = this.block.hasOutros && block.getUniqueName('outroBlock')
399398
if (outroBlock) {
399+
const outroArg = this.compiler.options.nestedTransitions ? ', outroing' : '';
400400
block.builders.init.addBlock(deindent`
401-
function ${outroBlock}(i, detach, fn) {
401+
function ${outroBlock}(i, detach, fn${outroArg}) {
402402
if (${iterations}[i]) {
403403
${iterations}[i].o(() => {
404404
if (detach) {
405405
${iterations}[i].d(detach);
406406
${iterations}[i] = null;
407407
}
408408
if (fn) fn();
409-
});
409+
}${outroArg});
410410
}
411411
}
412412
`);
@@ -451,7 +451,7 @@ export default class EachBlock extends Node {
451451
if (this.block.hasOutros) {
452452
destroy = deindent`
453453
@groupOutros();
454-
for (; #i < ${iterations}.length; #i += 1) ${outroBlock}(#i, 1);
454+
for (; #i < ${iterations}.length; #i += 1) ${outroBlock}(#i, 1${this.compiler.options.nestedTransitions && ', null, 1'});
455455
`;
456456
} else {
457457
destroy = deindent`
@@ -482,7 +482,7 @@ export default class EachBlock extends Node {
482482
block.builders.outro.addBlock(deindent`
483483
${iterations} = ${iterations}.filter(Boolean);
484484
const ${countdown} = @callAfter(#outrocallback, ${iterations}.length);
485-
for (let #i = 0; #i < ${iterations}.length; #i += 1) ${outroBlock}(#i, 0, ${countdown});`
485+
for (let #i = 0; #i < ${iterations}.length; #i += 1) ${outroBlock}(#i, 0, ${countdown}${this.compiler.options.nestedTransitions && ', 1'});`
486486
);
487487
}
488488

src/compile/nodes/Element.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -761,7 +761,7 @@ export default class Element extends Node {
761761
762762
#component.root._aftercreate.push(() => {
763763
if (!${name}) ${name} = @wrapTransition(#component, ${this.var}, ${fn}, ${snippet}, true);
764-
${name}.run(1);
764+
${name}.run(1${this.compiler.options.nestedTransitions && ', null, introing'});
765765
});
766766
`);
767767

@@ -770,7 +770,7 @@ export default class Element extends Node {
770770
${name}.run(0, () => {
771771
#outrocallback();
772772
${name} = null;
773-
});
773+
}${this.compiler.options.nestedTransitions && ', outroing'});
774774
`);
775775

776776
block.builders.destroy.addConditional('detach', `if (${name}) ${name}.abort();`);
@@ -796,7 +796,7 @@ export default class Element extends Node {
796796
block.builders.intro.addConditional(`#component.root._intro`, deindent`
797797
#component.root._aftercreate.push(() => {
798798
${introName} = @wrapTransition(#component, ${this.var}, ${fn}, ${snippet}, true);
799-
${introName}.run(1);
799+
${introName}.run(1${this.compiler.options.nestedTransitions && ', null, introing'});
800800
});
801801
`);
802802
}
@@ -817,7 +817,7 @@ export default class Element extends Node {
817817
// group) prior to their removal from the DOM
818818
block.builders.outro.addBlock(deindent`
819819
${outroName} = @wrapTransition(#component, ${this.var}, ${fn}, ${snippet}, false);
820-
${outroName}.run(0, #outrocallback);
820+
${outroName}.run(0, #outrocallback${this.compiler.options.nestedTransitions && ', outroing'});
821821
`);
822822

823823
block.builders.destroy.addConditional('detach', `if (${outroName}) ${outroName}.abort();`);

src/compile/nodes/IfBlock.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ export default class IfBlock extends Node {
140140

141141
if (this.compiler.options.nestedTransitions) {
142142
block.builders.outro.addBlock(deindent`
143-
if (${name}) ${name}.o(#outrocallback);
143+
if (${name}) ${name}.o(#outrocallback, 1);
144144
else #outrocallback();
145145
`);
146146
}
@@ -152,7 +152,7 @@ export default class IfBlock extends Node {
152152

153153
if (hasOutros && this.compiler.options.nestedTransitions) {
154154
block.builders.outro.addBlock(deindent`
155-
if (${name}) ${name}.o(#outrocallback);
155+
if (${name}) ${name}.o(#outrocallback, 1);
156156
else #outrocallback();
157157
`);
158158
}
@@ -206,7 +206,7 @@ export default class IfBlock extends Node {
206206
const initialMountNode = parentNode || '#target';
207207
const anchorNode = parentNode ? 'null' : 'anchor';
208208
block.builders.mount.addLine(
209-
`${if_name}${name}.${mountOrIntro}(${initialMountNode}, ${anchorNode});`
209+
`${if_name}${name}.${mountOrIntro}(${initialMountNode}, ${anchorNode}${this.compiler.options.nestedTransitions ? ', 1' : ''});`
210210
);
211211

212212
const updateMountNode = this.getUpdateMountNode(anchor);
@@ -292,7 +292,7 @@ export default class IfBlock extends Node {
292292
const anchorNode = parentNode ? 'null' : 'anchor';
293293

294294
block.builders.mount.addLine(
295-
`${if_current_block_type_index}${if_blocks}[${current_block_type_index}].${mountOrIntro}(${initialMountNode}, ${anchorNode});`
295+
`${if_current_block_type_index}${if_blocks}[${current_block_type_index}].${mountOrIntro}(${initialMountNode}, ${anchorNode}${this.compiler.options.nestedTransitions ? ', 1' : ''});`
296296
);
297297

298298
const updateMountNode = this.getUpdateMountNode(anchor);
@@ -374,7 +374,7 @@ export default class IfBlock extends Node {
374374
const anchorNode = parentNode ? 'null' : 'anchor';
375375

376376
block.builders.mount.addLine(
377-
`if (${name}) ${name}.${mountOrIntro}(${initialMountNode}, ${anchorNode});`
377+
`if (${name}) ${name}.${mountOrIntro}(${initialMountNode}, ${anchorNode}${this.compiler.options.nestedTransitions ? ', 1' : ''});`
378378
);
379379

380380
const updateMountNode = this.getUpdateMountNode(anchor);

src/shared/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,8 @@ export function callAll(fns) {
147147
while (fns && fns.length) fns.shift()();
148148
}
149149

150-
export function _mount(target, anchor) {
151-
this._fragment[this._fragment.i ? 'i' : 'm'](target, anchor || null);
150+
export function _mount(target, anchor, introing) {
151+
this._fragment[this._fragment.i ? 'i' : 'm'](target, anchor || null, introing);
152152
}
153153

154154
export var PENDING = {};

src/shared/transitions.js

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { createElement } from './dom.js';
2-
import { noop, run } from './utils.js';
2+
import { noop, run, assign } from './utils.js';
33

44
export function linear(t) {
55
return t;
@@ -28,6 +28,7 @@ export function hash(str) {
2828

2929
export function wrapTransition(component, node, fn, params, intro) {
3030
let obj = fn.call(component, node, params);
31+
if (typeof obj !== 'function') obj = assign(assign({}, component.root.options.transitions), obj);
3132
let duration;
3233
let ease;
3334
let cssText;
@@ -40,28 +41,35 @@ export function wrapTransition(component, node, fn, params, intro) {
4041
program: null,
4142
pending: null,
4243

43-
run(b, callback) {
44+
run(b, callback, introOutro) {
4445
if (typeof obj === 'function') {
4546
transitionManager.wait().then(() => {
4647
obj = obj();
47-
this._run(b, callback);
48+
obj = assign(assign({}, component.root.options.transitions), obj);
49+
this._run(b, callback, introOutro);
4850
});
4951
} else {
50-
this._run(b, callback);
52+
this._run(b, callback, introOutro);
5153
}
5254
},
5355

54-
_run(b, callback) {
56+
_run(b, callback, introOutro) {
5557
duration = obj.duration || 300;
5658
ease = obj.easing || linear;
5759

60+
if (introOutro && ((b && obj.intro === false) || (!b && obj.outro === false))) {
61+
this.t = b;
62+
if (callback) callback();
63+
return;
64+
}
65+
5866
const program = {
5967
start: window.performance.now() + (obj.delay || 0),
6068
b,
6169
callback: callback || noop
6270
};
6371

64-
if (intro && !initialised) {
72+
if (b && !initialised) {
6573
if (obj.css && obj.delay) {
6674
cssText = node.style.cssText;
6775
node.style.cssText += obj.css(0, 1);

test/cli/samples/amd/expected/Main.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,8 @@ define("test", function() { "use strict";
165165
assign(this._staged, newState);
166166
}
167167

168-
function _mount(target, anchor) {
169-
this._fragment[this._fragment.i ? 'i' : 'm'](target, anchor || null);
168+
function _mount(target, anchor, introing) {
169+
this._fragment[this._fragment.i ? 'i' : 'm'](target, anchor || null, introing);
170170
}
171171

172172
function _differs(a, b) {

test/cli/samples/basic/expected/Main.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,8 @@ function _stage(newState) {
165165
assign(this._staged, newState);
166166
}
167167

168-
function _mount(target, anchor) {
169-
this._fragment[this._fragment.i ? 'i' : 'm'](target, anchor || null);
168+
function _mount(target, anchor, introing) {
169+
this._fragment[this._fragment.i ? 'i' : 'm'](target, anchor || null, introing);
170170
}
171171

172172
function _differs(a, b) {

test/cli/samples/custom-element/expected/Main.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,8 @@ function _stage(newState) {
186186
assign(this._staged, newState);
187187
}
188188

189-
function _mount(target, anchor) {
190-
this._fragment[this._fragment.i ? 'i' : 'm'](target, anchor || null);
189+
function _mount(target, anchor, introing) {
190+
this._fragment[this._fragment.i ? 'i' : 'm'](target, anchor || null, introing);
191191
}
192192

193193
function _differs(a, b) {

test/cli/samples/dev/expected/Main.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,8 @@ function _stage(newState) {
191191
assign(this._staged, newState);
192192
}
193193

194-
function _mount(target, anchor) {
195-
this._fragment[this._fragment.i ? 'i' : 'm'](target, anchor || null);
194+
function _mount(target, anchor, introing) {
195+
this._fragment[this._fragment.i ? 'i' : 'm'](target, anchor || null, introing);
196196
}
197197

198198
function _differs(a, b) {

test/cli/samples/dir-sourcemap/expected/Main.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/cli/samples/dir-sourcemap/expected/Widget.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/cli/samples/dir-subdir/expected/Main.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,8 @@ function _stage(newState) {
167167
assign(this._staged, newState);
168168
}
169169

170-
function _mount(target, anchor) {
171-
this._fragment[this._fragment.i ? 'i' : 'm'](target, anchor || null);
170+
function _mount(target, anchor, introing) {
171+
this._fragment[this._fragment.i ? 'i' : 'm'](target, anchor || null, introing);
172172
}
173173

174174
function _differs(a, b) {

test/cli/samples/dir-subdir/expected/widget/Widget.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,8 @@ function _stage(newState) {
165165
assign(this._staged, newState);
166166
}
167167

168-
function _mount(target, anchor) {
169-
this._fragment[this._fragment.i ? 'i' : 'm'](target, anchor || null);
168+
function _mount(target, anchor, introing) {
169+
this._fragment[this._fragment.i ? 'i' : 'm'](target, anchor || null, introing);
170170
}
171171

172172
function _differs(a, b) {

0 commit comments

Comments
 (0)