Skip to content

Commit eccc8b2

Browse files
authored
Implement local transitions — fixes #1480
1 parent ebd0b5e commit eccc8b2

File tree

31 files changed

+688
-72
lines changed

31 files changed

+688
-72
lines changed

src/compile/nodes/Transition.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export default class Transition extends Node {
77
name: string;
88
directive: string;
99
expression: Expression;
10+
is_local: boolean;
1011

1112
constructor(component: Component, parent, scope, info) {
1213
super(component, parent, scope, info);
@@ -15,6 +16,7 @@ export default class Transition extends Node {
1516

1617
this.name = info.name;
1718
this.directive = info.intro && info.outro ? 'transition' : info.intro ? 'in' : 'out';
19+
this.is_local = info.modifiers.includes('local');
1820

1921
if ((info.intro && parent.intro) || (info.outro && parent.outro)) {
2022
const parentTransition = (parent.intro || parent.outro);

src/compile/render-dom/Block.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -174,13 +174,15 @@ export default class Block {
174174
}
175175
}
176176

177-
addIntro() {
177+
addIntro(local?: boolean) {
178178
this.hasIntros = this.hasIntroMethod = this.renderer.hasIntroTransitions = true;
179+
if (!local && this.parent) this.parent.addIntro();
179180
}
180181

181-
addOutro() {
182+
addOutro(local?: boolean) {
182183
this.hasOutros = this.hasOutroMethod = this.renderer.hasOutroTransitions = true;
183184
this.outros += 1;
185+
if (!local && this.parent) this.parent.addOutro();
184186
}
185187

186188
addAnimation() {
@@ -327,7 +329,7 @@ export default class Block {
327329
properties.addLine(`i: @noop,`);
328330
} else {
329331
properties.addBlock(deindent`
330-
${dev ? 'i: function intro' : 'i'}() {
332+
${dev ? 'i: function intro' : 'i'}(#local) {
331333
${this.hasOutros && `if (#current) return;`}
332334
${this.builders.intro}
333335
},
@@ -338,7 +340,7 @@ export default class Block {
338340
properties.addLine(`o: @noop,`);
339341
} else {
340342
properties.addBlock(deindent`
341-
${dev ? 'o: function outro' : 'o'}() {
343+
${dev ? 'o: function outro' : 'o'}(#local) {
342344
${this.builders.outro}
343345
},
344346
`);

src/compile/render-dom/wrappers/EachBlock.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ export default class EachBlockWrapper extends Wrapper {
403403
const outroBlock = this.block.hasOutros && block.getUniqueName('outroBlock')
404404
if (outroBlock) {
405405
block.builders.init.addBlock(deindent`
406-
function ${outroBlock}(i, detach) {
406+
function ${outroBlock}(i, detach, local) {
407407
if (${iterations}[i]) {
408408
if (detach) {
409409
@on_outro(() => {
@@ -412,7 +412,7 @@ export default class EachBlockWrapper extends Wrapper {
412412
});
413413
}
414414
415-
${iterations}[i].o();
415+
${iterations}[i].o(local);
416416
}
417417
}
418418
`);
@@ -434,27 +434,27 @@ export default class EachBlockWrapper extends Wrapper {
434434
${iterations}[#i].c();
435435
${iterations}[#i].m(${updateMountNode}, ${anchor});
436436
}
437-
${has_transitions && `${iterations}[#i].i();`}
437+
${has_transitions && `${iterations}[#i].i(1);`}
438438
`
439439
: deindent`
440440
${iterations}[#i] = ${create_each_block}(child_ctx);
441441
${iterations}[#i].c();
442442
${iterations}[#i].m(${updateMountNode}, ${anchor});
443-
${has_transitions && `${iterations}[#i].i();`}
443+
${has_transitions && `${iterations}[#i].i(1);`}
444444
`;
445445

446446
const start = this.block.hasUpdateMethod ? '0' : `${iterations}.length`;
447447

448-
let destroy;
448+
let remove_old_blocks;
449449

450450
if (this.block.hasOutros) {
451-
destroy = deindent`
451+
remove_old_blocks = deindent`
452452
@group_outros();
453-
for (; #i < ${iterations}.length; #i += 1) ${outroBlock}(#i, 1);
453+
for (; #i < ${iterations}.length; #i += 1) ${outroBlock}(#i, 1, 1);
454454
@check_outros();
455455
`;
456456
} else {
457-
destroy = deindent`
457+
remove_old_blocks = deindent`
458458
for (${this.block.hasUpdateMethod ? `` : `#i = ${this.vars.each_block_value}.${length}`}; #i < ${iterations}.length; #i += 1) {
459459
${iterations}[#i].d(1);
460460
}
@@ -471,7 +471,7 @@ export default class EachBlockWrapper extends Wrapper {
471471
${forLoopBody}
472472
}
473473
474-
${destroy}
474+
${remove_old_blocks}
475475
`;
476476

477477
block.builders.update.addBlock(deindent`

src/compile/render-dom/wrappers/Element/index.ts

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,8 @@ export default class ElementWrapper extends Wrapper {
162162
this.bindings = this.node.bindings.map(binding => new Binding(block, binding, this));
163163

164164
if (node.intro || node.outro) {
165-
if (node.intro) block.addIntro();
166-
if (node.outro) block.addOutro();
165+
if (node.intro) block.addIntro(node.intro.is_local);
166+
if (node.outro) block.addOutro(node.outro.is_local);
167167
}
168168

169169
if (node.animation) {
@@ -622,17 +622,34 @@ export default class ElementWrapper extends Wrapper {
622622

623623
const fn = component.qualify(intro.name);
624624

625-
block.builders.intro.addBlock(deindent`
625+
const intro_block = deindent`
626626
@add_render_callback(() => {
627627
if (!${name}) ${name} = @create_bidirectional_transition(${this.var}, ${fn}, ${snippet}, true);
628628
${name}.run(1);
629629
});
630-
`);
630+
`;
631631

632-
block.builders.outro.addBlock(deindent`
632+
const outro_block = deindent`
633633
if (!${name}) ${name} = @create_bidirectional_transition(${this.var}, ${fn}, ${snippet}, false);
634634
${name}.run(0);
635-
`);
635+
`;
636+
637+
if (intro.is_local) {
638+
block.builders.intro.addBlock(deindent`
639+
if (#local) {
640+
${intro_block}
641+
}
642+
`);
643+
644+
block.builders.outro.addBlock(deindent`
645+
if (#local) {
646+
${outro_block}
647+
}
648+
`);
649+
} else {
650+
block.builders.intro.addBlock(intro_block);
651+
block.builders.outro.addBlock(outro_block);
652+
}
636653

637654
block.builders.destroy.addConditional('detach', `if (${name}) ${name}.end();`);
638655
}
@@ -649,25 +666,37 @@ export default class ElementWrapper extends Wrapper {
649666

650667
const fn = component.qualify(intro.name);
651668

669+
let intro_block;
670+
652671
if (outro) {
653-
block.builders.intro.addBlock(deindent`
672+
intro_block = deindent`
654673
@add_render_callback(() => {
655674
if (!${introName}) ${introName} = @create_in_transition(${this.var}, ${fn}, ${snippet});
656675
${introName}.start();
657676
});
658-
`);
677+
`;
659678

660679
block.builders.outro.addLine(`if (${introName}) ${introName}.invalidate()`);
661680
} else {
662-
block.builders.intro.addBlock(deindent`
681+
intro_block = deindent`
663682
if (!${introName}) {
664683
@add_render_callback(() => {
665684
${introName} = @create_in_transition(${this.var}, ${fn}, ${snippet});
666685
${introName}.start();
667686
});
668687
}
669-
`);
688+
`;
689+
}
690+
691+
if (intro.is_local) {
692+
intro_block = deindent`
693+
if (#local) {
694+
${intro_block}
695+
}
696+
`;
670697
}
698+
699+
block.builders.intro.addBlock(intro_block);
671700
}
672701

673702
if (outro) {
@@ -684,9 +713,19 @@ export default class ElementWrapper extends Wrapper {
684713

685714
// TODO hide elements that have outro'd (unless they belong to a still-outroing
686715
// group) prior to their removal from the DOM
687-
block.builders.outro.addBlock(deindent`
716+
let outro_block = deindent`
688717
${outroName} = @create_out_transition(${this.var}, ${fn}, ${snippet});
689-
`);
718+
`;
719+
720+
if (outro_block) {
721+
outro_block = deindent`
722+
if (#local) {
723+
${outro_block}
724+
}
725+
`;
726+
}
727+
728+
block.builders.outro.addBlock(outro_block);
690729

691730
block.builders.destroy.addConditional('detach', `if (${outroName}) ${outroName}.end();`);
692731
}

src/compile/render-dom/wrappers/IfBlock.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,6 @@ export default class IfBlockWrapper extends Wrapper {
125125

126126
createBranches(this.node);
127127

128-
if (hasIntros) block.addIntro();
129-
if (hasOutros) block.addOutro();
130-
131128
blocks.forEach(block => {
132129
block.hasUpdateMethod = isDynamic;
133130
block.hasIntroMethod = hasIntros;
@@ -239,7 +236,7 @@ export default class IfBlockWrapper extends Wrapper {
239236
if (${name}) {
240237
${name}.c();
241238
${name}.m(${updateMountNode}, ${anchor});
242-
${has_transitions && `${name}.i();`}
239+
${has_transitions && `${name}.i(1);`}
243240
}
244241
`;
245242

@@ -327,7 +324,7 @@ export default class IfBlockWrapper extends Wrapper {
327324
${if_blocks}[${previous_block_index}].d(1);
328325
${if_blocks}[${previous_block_index}] = null;
329326
});
330-
${name}.o();
327+
${name}.o(1);
331328
@check_outros();
332329
`;
333330

@@ -338,7 +335,7 @@ export default class IfBlockWrapper extends Wrapper {
338335
${name}.c();
339336
}
340337
${name}.m(${updateMountNode}, ${anchor});
341-
${has_transitions && `${name}.i();`}
338+
${has_transitions && `${name}.i(1);`}
342339
`;
343340

344341
const changeBlock = hasElse
@@ -415,15 +412,15 @@ export default class IfBlockWrapper extends Wrapper {
415412
${name}.c();
416413
${name}.m(${updateMountNode}, ${anchor});
417414
}
418-
${has_transitions && `${name}.i();`}
415+
${has_transitions && `${name}.i(1);`}
419416
`
420417
: deindent`
421418
if (!${name}) {
422419
${name} = ${branch.block.name}(ctx);
423420
${name}.c();
424421
${name}.m(${updateMountNode}, ${anchor});
425422
}
426-
${has_transitions && `${name}.i();`}
423+
${has_transitions && `${name}.i(1);`}
427424
`;
428425

429426
// no `p()` here — we don't want to update outroing nodes,
@@ -436,7 +433,7 @@ export default class IfBlockWrapper extends Wrapper {
436433
${name} = null;
437434
});
438435
439-
${name}.o();
436+
${name}.o(1);
440437
@check_outros();
441438
`
442439
: deindent`

src/compile/render-dom/wrappers/InlineComponent/index.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ export default class InlineComponentWrapper extends Wrapper {
397397
@on_outro(() => {
398398
old_component.$destroy();
399399
});
400-
old_component.$$.fragment.o();
400+
old_component.$$.fragment.o(1);
401401
@check_outros();
402402
}
403403
@@ -409,15 +409,15 @@ export default class InlineComponentWrapper extends Wrapper {
409409
410410
${name}.$$.fragment.c();
411411
@mount_component(${name}, ${updateMountNode}, ${anchor});
412-
${name}.$$.fragment.i();
412+
${name}.$$.fragment.i(1);
413413
} else {
414414
${name} = null;
415415
}
416416
}
417417
`);
418418

419419
block.builders.intro.addBlock(deindent`
420-
if (${name}) ${name}.$$.fragment.i();
420+
if (${name}) ${name}.$$.fragment.i(#local);
421421
`);
422422

423423
if (updates.length) {
@@ -430,6 +430,10 @@ export default class InlineComponentWrapper extends Wrapper {
430430
`);
431431
}
432432

433+
block.builders.outro.addLine(
434+
`if (${name}) ${name}.$$.fragment.o(#local);`
435+
);
436+
433437
block.builders.destroy.addLine(`if (${name}) ${name}.$destroy(${parentNode ? '' : 'detach'});`);
434438
} else {
435439
const expression = this.node.name === 'svelte:self'
@@ -459,7 +463,7 @@ export default class InlineComponentWrapper extends Wrapper {
459463
);
460464

461465
block.builders.intro.addBlock(deindent`
462-
${name}.$$.fragment.i();
466+
${name}.$$.fragment.i(#local);
463467
`);
464468

465469
if (updates.length) {
@@ -473,11 +477,11 @@ export default class InlineComponentWrapper extends Wrapper {
473477
block.builders.destroy.addBlock(deindent`
474478
${name}.$destroy(${parentNode ? '' : 'detach'});
475479
`);
476-
}
477480

478-
block.builders.outro.addLine(
479-
`if (${name}) ${name}.$$.fragment.o();`
480-
);
481+
block.builders.outro.addLine(
482+
`${name}.$$.fragment.o(#local);`
483+
);
484+
}
481485
}
482486
}
483487

src/internal/await-block.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export function handlePromise(promise, info) {
2222
block.d(1);
2323
info.blocks[i] = null;
2424
});
25-
block.o();
25+
block.o(1);
2626
check_outros();
2727
}
2828
});
@@ -32,7 +32,7 @@ export function handlePromise(promise, info) {
3232

3333
block.c();
3434
block.m(info.mount(), info.anchor);
35-
if (block.i) block.i();
35+
if (block.i) block.i(1);
3636

3737
flush();
3838
}

src/internal/keyed-each.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export function outroAndDestroyBlock(block, lookup) {
1010
destroyBlock(block, lookup);
1111
});
1212

13-
block.o();
13+
block.o(1);
1414
}
1515

1616
export function fixAndOutroAndDestroyBlock(block, lookup) {
@@ -53,7 +53,7 @@ export function updateKeyedEach(old_blocks, changed, get_key, dynamic, ctx, list
5353

5454
function insert(block) {
5555
block.m(node, next);
56-
if (block.i) block.i();
56+
if (block.i) block.i(1);
5757
lookup[block.key] = block;
5858
next = block.first;
5959
n--;

0 commit comments

Comments
 (0)