From 0e76f5189abdb5dd9f9dd548aec73d48aecaac5b Mon Sep 17 00:00:00 2001 From: makhnatkin Date: Fri, 4 Oct 2024 10:05:04 +0200 Subject: [PATCH] feat(srcDoc): updtaed handleHashChange logic --- src/runtime/SrcDocIFrameController.ts | 29 ++++++++++++++++----------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/runtime/SrcDocIFrameController.ts b/src/runtime/SrcDocIFrameController.ts index 64c0f98..523d833 100644 --- a/src/runtime/SrcDocIFrameController.ts +++ b/src/runtime/SrcDocIFrameController.ts @@ -5,6 +5,8 @@ import {DEFAULT_IFRAME_HEIGHT_PADDING} from '../constants'; import {IEmbeddedContentController} from './IEmbeddedContentController'; +const PARENT_LOADED_AND_RESIZED_TIMEOUT = 500; + const validateHostElement: (el: HTMLElement) => asserts el is HTMLIFrameElement = (el) => { if (!(el instanceof HTMLIFrameElement && el.dataset.yfmSandboxMode === 'srcdoc')) { throw new Error('Host element for `srcdoc` embedding mode was not configured properly'); @@ -96,36 +98,39 @@ export class SrcDocIFrameController extends Disposable implements IEmbeddedConte } } + setRootClassNames(classNames: string[] | undefined) { + return this.executeOnController((controller) => controller.setClassNames(classNames)); + } + + setRootStyles(styles: Record | undefined) { + return this.executeOnController((controller) => controller.setStyles(styles)); + } + private scrollToHash() { const hash = window.location.hash.substring(1); if (hash) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const document = this.host.contentWindow!.document; const element = document.getElementById(hash); if (element) { - element.scrollIntoView({ behavior: 'smooth' }); + element.scrollIntoView({behavior: 'smooth'}); } } } private async handleHashChange() { - await ensureIframeLoaded(this.host); - - this.scrollToHash(); + // цait until all iframes managed by the parent controller are fully loaded, + // and parent containers have heights properly adjusted. + setTimeout(() => { + this.scrollToHash(); + }, PARENT_LOADED_AND_RESIZED_TIMEOUT); const handleHashChange = () => this.scrollToHash(); window.addEventListener('hashchange', handleHashChange); this.dispose.add(() => window.removeEventListener('hashchange', handleHashChange)); } - setRootClassNames(classNames: string[] | undefined) { - return this.executeOnController((controller) => controller.setClassNames(classNames)); - } - - setRootStyles(styles: Record | undefined) { - return this.executeOnController((controller) => controller.setStyles(styles)); - } - private async instantiateController() { await ensureIframeLoaded(this.host);