Skip to content

Commit 736f930

Browse files
committed
feat: add view transition events
1 parent 5404201 commit 736f930

File tree

1 file changed

+60
-12
lines changed

1 file changed

+60
-12
lines changed

packages/router-core/src/router.ts

Lines changed: 60 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,10 @@ type NavigationEventInfo = {
544544
hashChanged: boolean
545545
}
546546

547+
export type ViewTransitionEventInfo = {
548+
transition: ViewTransition
549+
}
550+
547551
export interface RouterEvents {
548552
onBeforeNavigate: {
549553
type: 'onBeforeNavigate'
@@ -563,6 +567,22 @@ export interface RouterEvents {
563567
onRendered: {
564568
type: 'onRendered'
565569
} & NavigationEventInfo
570+
onViewTransitionStart: {
571+
type: 'onViewTransitionStart'
572+
} & ViewTransitionEventInfo &
573+
NavigationEventInfo
574+
onViewTransitionReady: {
575+
type: 'onViewTransitionReady'
576+
} & ViewTransitionEventInfo &
577+
NavigationEventInfo
578+
onViewTransitionUpdateCallbackDone: {
579+
type: 'onViewTransitionUpdateCallbackDone'
580+
} & ViewTransitionEventInfo &
581+
NavigationEventInfo
582+
onViewTransitionFinish: {
583+
type: 'onViewTransitionFinish'
584+
} & ViewTransitionEventInfo &
585+
NavigationEventInfo
566586
}
567587

568588
export type RouterEvent = RouterEvents[keyof RouterEvents]
@@ -827,6 +847,7 @@ export function getLocationChangeInfo(routerState: {
827847
const hashChanged = fromLocation?.hash !== toLocation.hash
828848
return { fromLocation, toLocation, pathChanged, hrefChanged, hashChanged }
829849
}
850+
export type LocationChangeInfo = ReturnType<typeof getLocationChangeInfo>
830851

831852
export type CreateRouterFn = <
832853
TRouteTree extends AnyRoute,
@@ -2088,22 +2109,21 @@ export class RouterCore<
20882109
const next = this.latestLocation
20892110
const prevLocation = this.state.resolvedLocation
20902111

2112+
const locationChangeInfo = getLocationChangeInfo({
2113+
resolvedLocation: prevLocation,
2114+
location: next,
2115+
})
2116+
20912117
if (!this.state.redirect) {
20922118
this.emit({
20932119
type: 'onBeforeNavigate',
2094-
...getLocationChangeInfo({
2095-
resolvedLocation: prevLocation,
2096-
location: next,
2097-
}),
2120+
...locationChangeInfo,
20982121
})
20992122
}
21002123

21012124
this.emit({
21022125
type: 'onBeforeLoad',
2103-
...getLocationChangeInfo({
2104-
resolvedLocation: prevLocation,
2105-
location: next,
2106-
}),
2126+
...locationChangeInfo,
21072127
})
21082128

21092129
await loadMatches({
@@ -2114,10 +2134,9 @@ export class RouterCore<
21142134
updateMatch: this.updateMatch,
21152135
// eslint-disable-next-line @typescript-eslint/require-await
21162136
onReady: async () => {
2117-
// eslint-disable-next-line @typescript-eslint/require-await
21182137
// Wrap batch in framework-specific transition wrapper (e.g., Solid's startTransition)
21192138
this.startTransition(() => {
2120-
this.startViewTransition(async () => {
2139+
this.startViewTransition(locationChangeInfo, async () => {
21212140
// this.viewTransitionPromise = createControlledPromise<true>()
21222141

21232142
// Commit the pending matches. If a previous match was
@@ -2237,7 +2256,10 @@ export class RouterCore<
22372256
}
22382257
}
22392258

2240-
startViewTransition = (fn: () => Promise<void>) => {
2259+
startViewTransition = (
2260+
locationChangeInfo: LocationChangeInfo,
2261+
fn: () => Promise<void>,
2262+
) => {
22412263
// Determine if we should start a view transition from the navigation
22422264
// or from the router default
22432265
const shouldViewTransition =
@@ -2286,7 +2308,33 @@ export class RouterCore<
22862308
startViewTransitionParams = fn
22872309
}
22882310

2289-
document.startViewTransition(startViewTransitionParams)
2311+
const transition = document.startViewTransition(startViewTransitionParams)
2312+
this.emit({
2313+
type: 'onViewTransitionStart',
2314+
transition,
2315+
...locationChangeInfo,
2316+
})
2317+
transition.ready.then(() => {
2318+
this.emit({
2319+
type: 'onViewTransitionReady',
2320+
transition,
2321+
...locationChangeInfo,
2322+
})
2323+
})
2324+
transition.updateCallbackDone.then(() => {
2325+
this.emit({
2326+
type: 'onViewTransitionUpdateCallbackDone',
2327+
transition,
2328+
...locationChangeInfo,
2329+
})
2330+
})
2331+
transition.finished.then(() => {
2332+
this.emit({
2333+
type: 'onViewTransitionFinish',
2334+
transition,
2335+
...locationChangeInfo,
2336+
})
2337+
})
22902338
} else {
22912339
fn()
22922340
}

0 commit comments

Comments
 (0)