diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js index e5302a3a7c..cf65e55f99 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js @@ -2548,22 +2548,24 @@ export const template_visitors = { context.visit(node.consequent) ); - context.state.after_update.push( - b.stmt( - b.call( - '$.if', - context.state.node, - b.thunk(/** @type {import('estree').Expression} */ (context.visit(node.test))), - b.arrow([b.id('$$anchor')], consequent), - node.alternate - ? b.arrow( - [b.id('$$anchor')], - /** @type {import('estree').BlockStatement} */ (context.visit(node.alternate)) - ) - : b.literal(null) - ) - ) - ); + const args = [ + context.state.node, + b.thunk(/** @type {import('estree').Expression} */ (context.visit(node.test))), + b.arrow([b.id('$$anchor')], consequent), + node.alternate + ? b.arrow( + [b.id('$$anchor')], + /** @type {import('estree').BlockStatement} */ (context.visit(node.alternate)) + ) + : b.literal(null) + ]; + + if (node.elseif) { + // the additional effect layer shouldn't affect local transitions + args.push(b.literal(true)); + } + + context.state.after_update.push(b.stmt(b.call('$.if', ...args))); }, AwaitBlock(node, context) { context.state.template.push(''); diff --git a/packages/svelte/src/internal/client/constants.js b/packages/svelte/src/internal/client/constants.js index 794a04ebb8..96d4c94f3b 100644 --- a/packages/svelte/src/internal/client/constants.js +++ b/packages/svelte/src/internal/client/constants.js @@ -9,6 +9,7 @@ export const DIRTY = 1 << 9; export const MAYBE_DIRTY = 1 << 10; export const INERT = 1 << 11; export const DESTROYED = 1 << 12; +export const IS_ELSEIF = 1 << 13; export const ROOT_BLOCK = 0; export const IF_BLOCK = 1; diff --git a/packages/svelte/src/internal/client/dom/blocks/if.js b/packages/svelte/src/internal/client/dom/blocks/if.js index db26f7c642..bb3bf21d77 100644 --- a/packages/svelte/src/internal/client/dom/blocks/if.js +++ b/packages/svelte/src/internal/client/dom/blocks/if.js @@ -1,4 +1,4 @@ -import { IF_BLOCK, UNINITIALIZED } from '../../constants.js'; +import { IF_BLOCK, IS_ELSEIF, UNINITIALIZED } from '../../constants.js'; import { current_hydration_fragment, hydrate_block_anchor, @@ -37,9 +37,10 @@ function create_if_block() { * @param {() => boolean} condition_fn * @param {(anchor: Node) => void} consequent_fn * @param {null | ((anchor: Node) => void)} alternate_fn + * @param {boolean} [elseif] * @returns {void} */ -export function if_block(anchor_node, condition_fn, consequent_fn, alternate_fn) { +export function if_block(anchor_node, condition_fn, consequent_fn, alternate_fn, elseif = false) { const block = create_if_block(); hydrate_block_anchor(anchor_node); @@ -153,6 +154,8 @@ export function if_block(anchor_node, condition_fn, consequent_fn, alternate_fn) } }, block); + if_effect.f |= IS_ELSEIF; + mismatch = false; // TODO not sure if we actually need this — belt and braces if_effect.ondestroy = () => { diff --git a/packages/svelte/src/internal/client/reactivity/effects.js b/packages/svelte/src/internal/client/reactivity/effects.js index 102cc9c6d5..f307737484 100644 --- a/packages/svelte/src/internal/client/reactivity/effects.js +++ b/packages/svelte/src/internal/client/reactivity/effects.js @@ -20,7 +20,8 @@ import { EFFECT, PRE_EFFECT, DESTROYED, - INERT + INERT, + IS_ELSEIF } from '../constants.js'; import { set } from './sources.js'; import { noop } from '../../common.js'; @@ -300,7 +301,8 @@ function pause_children(effect, transitions, local) { if (effect.effects) { for (const child of effect.effects) { - pause_children(child, transitions, false); + var transparent = (child.f & IS_ELSEIF) !== 0 || (child.f & MANAGED) !== 0; + pause_children(child, transitions, transparent ? local : false); } } } @@ -323,7 +325,8 @@ function resume_children(effect, local) { if (effect.effects) { for (const child of effect.effects) { - resume_children(child, false); + var transparent = (child.f & IS_ELSEIF) !== 0 || (child.f & MANAGED) !== 0; + resume_children(child, transparent ? local : false); } }