From 45c5528e7fba5c2a76bdbc930c6ed3740e320a46 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Thu, 7 Dec 2023 15:58:33 +0000 Subject: [PATCH] fix: support dynamic transition functions --- .changeset/giant-roses-press.md | 5 ++++ .../3-transform/client/visitors/template.js | 4 ++-- packages/svelte/src/internal/client/render.js | 24 +++++++++---------- .../svelte/src/internal/client/transitions.js | 9 +++++-- 4 files changed, 26 insertions(+), 16 deletions(-) create mode 100644 .changeset/giant-roses-press.md diff --git a/.changeset/giant-roses-press.md b/.changeset/giant-roses-press.md new file mode 100644 index 0000000000..68069e0273 --- /dev/null +++ b/.changeset/giant-roses-press.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: support dynamic transition functions 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 4ec77b167d..e1e62e59fb 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 @@ -1767,7 +1767,7 @@ export const template_visitors = { b.call( '$.animate', state.node, - /** @type {import('estree').Expression} */ (visit(parse_directive_name(node.name))), + b.thunk(/** @type {import('estree').Expression} */ (visit(parse_directive_name(node.name)))), expression ) ) @@ -1791,7 +1791,7 @@ export const template_visitors = { b.call( type, state.node, - /** @type {import('estree').Expression} */ (visit(parse_directive_name(node.name))), + b.thunk(/** @type {import('estree').Expression} */ (visit(parse_directive_name(node.name)))), expression, node.modifiers.includes('global') ? b.true : b.false ) diff --git a/packages/svelte/src/internal/client/render.js b/packages/svelte/src/internal/client/render.js index c4161018dc..3033209629 100644 --- a/packages/svelte/src/internal/client/render.js +++ b/packages/svelte/src/internal/client/render.js @@ -2086,49 +2086,49 @@ export function html(dom, get_value, svg) { /** * @template P * @param {HTMLElement} dom - * @param {import('./types.js').TransitionFn

} transition_fn + * @param {() => import('./types.js').TransitionFn

} get_transition_fn * @param {(() => P) | null} props * @param {any} global * @returns {void} */ -export function transition(dom, transition_fn, props, global = false) { - bind_transition(dom, transition_fn, props, 'both', global); +export function transition(dom, get_transition_fn, props, global = false) { + bind_transition(dom, get_transition_fn, props, 'both', global); } /** * @template P * @param {HTMLElement} dom - * @param {import('./types.js').TransitionFn

} transition_fn + * @param {() => import('./types.js').TransitionFn

} get_transition_fn * @param {(() => P) | null} props * @returns {void} */ -export function animate(dom, transition_fn, props) { - bind_transition(dom, transition_fn, props, 'key', false); +export function animate(dom, get_transition_fn, props) { + bind_transition(dom, get_transition_fn, props, 'key', false); } /** * @template P * @param {HTMLElement} dom - * @param {import('./types.js').TransitionFn

} transition_fn + * @param {() => import('./types.js').TransitionFn

} get_transition_fn * @param {(() => P) | null} props * @param {any} global * @returns {void} */ -function in_fn(dom, transition_fn, props, global = false) { - bind_transition(dom, transition_fn, props, 'in', global); +function in_fn(dom, get_transition_fn, props, global = false) { + bind_transition(dom, get_transition_fn, props, 'in', global); } export { in_fn as in }; /** * @template P * @param {HTMLElement} dom - * @param {import('./types.js').TransitionFn

} transition_fn + * @param {() => import('./types.js').TransitionFn

} get_transition_fn * @param {(() => P) | null} props * @param {any} global * @returns {void} */ -export function out(dom, transition_fn, props, global = false) { - bind_transition(dom, transition_fn, props, 'out', global); +export function out(dom, get_transition_fn, props, global = false) { + bind_transition(dom, get_transition_fn, props, 'out', global); } /** diff --git a/packages/svelte/src/internal/client/transitions.js b/packages/svelte/src/internal/client/transitions.js index 52d09f39cb..79519d81c2 100644 --- a/packages/svelte/src/internal/client/transitions.js +++ b/packages/svelte/src/internal/client/transitions.js @@ -411,13 +411,13 @@ function is_transition_block(block) { /** * @template P * @param {HTMLElement} dom - * @param {import('./types.js').TransitionFn

| import('./types.js').AnimateFn

} transition_fn + * @param {() => import('./types.js').TransitionFn

| import('./types.js').AnimateFn

} get_transition_fn * @param {(() => P) | null} props_fn * @param {'in' | 'out' | 'both' | 'key'} direction * @param {boolean} global * @returns {void} */ -export function bind_transition(dom, transition_fn, props_fn, direction, global) { +export function bind_transition(dom, get_transition_fn, props_fn, direction, global) { const transition_effect = /** @type {import('./types.js').EffectSignal} */ (current_effect); const block = current_block; const props = props_fn === null ? {} : props_fn(); @@ -458,6 +458,11 @@ export function bind_transition(dom, transition_fn, props_fn, direction, global) let transition; effect(() => { + if (transition !== undefined) { + // Destroy any existing transitions first + transition.x(); + } + const transition_fn = get_transition_fn(); /** @param {DOMRect} [from] */ const init = (from) => untrack(() =>