fix(client): preserve scroll position of preview iframe (#47870)
* fix(client): preserve scroll position of preview iframe * use existing frameContext instead of getting element * do not use type guard * remove unused type, add es2022 to ts-lib * move scroll functions into a class Co-authored-by: Shaun Hamilton <shauhami020@gmail.com>pull/48178/head
parent
7f1b136e40
commit
8ea0401c0a
|
@ -1,7 +1,7 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { mainPreviewId } from '../utils/frame';
|
||||
import { mainPreviewId, scrollManager } from '../utils/frame';
|
||||
|
||||
import './preview.css';
|
||||
|
||||
|
@ -29,6 +29,12 @@ function Preview({
|
|||
setIframeStatus(disableIframe);
|
||||
}, [disableIframe]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
scrollManager.setPreviewScrollPosition(0);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const id = previewId ?? mainPreviewId;
|
||||
|
||||
return (
|
||||
|
|
|
@ -41,6 +41,35 @@ type InitFrame = (
|
|||
frameConsoleLogger?: ProxyLogger
|
||||
) => (frameContext: Context) => Context;
|
||||
|
||||
class ScrollManager {
|
||||
#previewScrollPosition = 0;
|
||||
|
||||
getPreviewScrollPosition = () => {
|
||||
return this.#previewScrollPosition;
|
||||
};
|
||||
|
||||
setPreviewScrollPosition = (position: number) => {
|
||||
this.#previewScrollPosition = position;
|
||||
};
|
||||
|
||||
registerScrollEventListener = (iframe: HTMLIFrameElement) => {
|
||||
iframe.contentDocument?.addEventListener('scroll', event => {
|
||||
const currentTarget = event.currentTarget as Document | null;
|
||||
if (currentTarget?.body.scrollTop) {
|
||||
this.setPreviewScrollPosition(currentTarget?.body.scrollTop);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
restorePreviewScrollPosition = (iframe: HTMLIFrameElement) => {
|
||||
if (iframe.contentDocument?.body) {
|
||||
iframe.contentDocument.body.scrollTop = this.#previewScrollPosition;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export const scrollManager = new ScrollManager();
|
||||
|
||||
// we use two different frames to make them all essentially pure functions
|
||||
// main iframe is responsible rendering the preview and is where we proxy the
|
||||
export const mainPreviewId = 'fcc-main-frame';
|
||||
|
@ -267,6 +296,12 @@ const writeContentToFrame = (frameContext: Context) => {
|
|||
createHeader(frameContext.element.id) + frameContext.build,
|
||||
frameContext.document
|
||||
);
|
||||
|
||||
scrollManager.registerScrollEventListener(frameContext.element);
|
||||
|
||||
if (scrollManager.getPreviewScrollPosition()) {
|
||||
scrollManager.restorePreviewScrollPosition(frameContext.element);
|
||||
}
|
||||
return frameContext;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue