@@ -215,6 +215,45 @@ async function updateDOM(
215
215
return null ;
216
216
} ;
217
217
218
+ type SavedFocus = {
219
+ activeElement : HTMLElement | null ;
220
+ start ?: number | null ;
221
+ end ?: number | null ;
222
+ } ;
223
+
224
+ const saveFocus = ( ) : SavedFocus => {
225
+ const activeElement = document . activeElement as HTMLElement ;
226
+ // The element that currently has the focus is part of a DOM tree
227
+ // that will survive the transition to the new document.
228
+ // Save the element and the cursor position
229
+ if ( activeElement ?. closest ( '[data-astro-transition-persist]' ) ) {
230
+ if (
231
+ activeElement instanceof HTMLInputElement ||
232
+ activeElement instanceof HTMLTextAreaElement
233
+ ) {
234
+ const start = activeElement . selectionStart ;
235
+ const end = activeElement . selectionEnd ;
236
+ return { activeElement, start, end } ;
237
+ }
238
+ return { activeElement } ;
239
+ } else {
240
+ return { activeElement : null } ;
241
+ }
242
+ } ;
243
+
244
+ const restoreFocus = ( { activeElement, start, end } : SavedFocus ) => {
245
+ if ( activeElement ) {
246
+ activeElement . focus ( ) ;
247
+ if (
248
+ activeElement instanceof HTMLInputElement ||
249
+ activeElement instanceof HTMLTextAreaElement
250
+ ) {
251
+ activeElement . selectionStart = start ! ;
252
+ activeElement . selectionEnd = end ! ;
253
+ }
254
+ }
255
+ } ;
256
+
218
257
const swap = ( ) => {
219
258
// swap attributes of the html element
220
259
// - delete all attributes from the current document
@@ -263,6 +302,8 @@ async function updateDOM(
263
302
// Persist elements in the existing body
264
303
const oldBody = document . body ;
265
304
305
+ const savedFocus = saveFocus ( ) ;
306
+
266
307
// this will reset scroll Position
267
308
document . body . replaceWith ( newDocument . body ) ;
268
309
for ( const el of oldBody . querySelectorAll ( `[${ PERSIST_ATTR } ]` ) ) {
@@ -275,6 +316,8 @@ async function updateDOM(
275
316
}
276
317
}
277
318
319
+ restoreFocus ( savedFocus ) ;
320
+
278
321
if ( popState ) {
279
322
scrollTo ( popState . scrollX , popState . scrollY ) ; // usings 'auto' scrollBehavior
280
323
} else {
0 commit comments