Skip to content

Commit 168fc41

Browse files
committed
fix(transition): fix reactive state to prevent jumping
1 parent 7033aa7 commit 168fc41

File tree

3 files changed

+24
-18
lines changed

3 files changed

+24
-18
lines changed

src/lib/components/RouteComponent.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@
144144
});
145145
146146
// Trigger component resolution on route change
147-
$effect(() => {
147+
$effect.pre(() => {
148148
resolveComponent(component, listeners);
149149
});
150150
</script>

src/lib/components/RouteTransition.svelte

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,39 @@
11
<script lang="ts">
2-
import type { TransitionFunction, TransitionWithProps } from '@dvcol/svelte-utils/transition';
2+
import type { TransitionFunction } from '@dvcol/svelte-utils/transition';
33
import type { Snippet } from 'svelte';
44
55
import type { TransitionProps } from '~/models/component.model.js';
66
77
import { toStyle } from '@dvcol/common-utils/common/class';
88
import { mutation } from '@dvcol/svelte-utils/mutation';
99
10+
import { isTransitionFunction, isTransitionObject } from '~/models/component.model.js';
11+
1012
const { children, key, id, transition }: { children: Snippet; id: string; key: any | any[]; transition: TransitionProps } = $props();
1113
1214
let firstRender = $state(true);
13-
const first = $derived<TransitionProps['first']>(transition?.first ?? true);
14-
const skipTransition = () => {
15-
if (!firstRender) return false;
16-
firstRender = false;
17-
return first === false;
18-
};
19-
20-
const isTransitionFunction = (skip?: TransitionProps['first']): skip is TransitionFunction => typeof skip === 'function' && !!skip;
21-
const isTransitionObject = (skip?: TransitionProps['first']): skip is TransitionWithProps => typeof skip === 'object' && !!skip?.use;
15+
const first = transition?.first ?? true;
2216
2317
const _in = $derived<TransitionFunction>(((node, props, options) => {
24-
if (skipTransition()) return;
25-
if (firstRender && isTransitionFunction(first)) return first;
26-
if (firstRender && isTransitionObject(first)) return first.use;
18+
if (firstRender) {
19+
firstRender = false;
20+
if (first === false) return;
21+
if (isTransitionFunction(first)) return first(node, props, options);
22+
if (isTransitionObject(first)) return first.use(node, props ?? {}, options);
23+
}
2724
return transition?.in?.(node, props, options);
2825
}) as TransitionFunction);
29-
const _out = $derived<TransitionFunction>(((node, props, options) => {
30-
if (firstRender && first) return;
31-
return transition?.out?.(node, props, options);
32-
}) as TransitionFunction);
3326
3427
const _inParams = $derived.by(() => {
3528
if (firstRender && isTransitionObject(first) && first.props) return first.props;
3629
return transition?.params?.in ?? {};
3730
});
31+
32+
const _out = $derived<TransitionFunction>(((node, props, options) => {
33+
if (firstRender && first === false) return;
34+
return transition?.out?.(node, props, options);
35+
}) as TransitionFunction);
36+
3837
const _outParams = $derived(transition?.params?.out ?? {});
3938
4039
const _containerProps = $derived(transition?.props?.container);

src/lib/models/component.model.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,3 +183,10 @@ export type RouteViewProps<Name extends RouteName = any> = Pick<RouterViewProps<
183183
*/
184184
children?: Snippet;
185185
} & Partial<Record<Name, Route<Name>['component']>>;
186+
187+
export function isTransitionFunction(skip?: TransitionProps['first']): skip is TransitionFunction {
188+
return typeof skip === 'function' && !!skip;
189+
};
190+
export function isTransitionObject(skip?: TransitionProps['first']): skip is TransitionWithProps {
191+
return typeof skip === 'object' && !!skip?.use;
192+
};

0 commit comments

Comments
 (0)