UNPKG

@redocly/theme

Version:

Shared UI components lib

60 lines (53 loc) 2.07 kB
import type { NavigateFunction, NavigateOptions } from 'react-router-dom'; import { getNavbarElement } from './get-navbar-element'; import { withLoadProgress } from './with-load-progress'; export type HistoryOrigin = 'pm' | 'browser'; let lastNavigatedPath; // this is copy from portal/src/client/app/utils/loadAndNavigate.ts, for case when we need to run Redoc without Realm export async function loadAndNavigate({ navigate, to, origin = 'browser', options, }: { navigate: NavigateFunction; to: string; origin?: HistoryOrigin; options?: NavigateOptions; }) { lastNavigatedPath = to; const { pathname, hash, search } = new URL(to, window.location.origin + window.location.pathname); // use window-shared loader instead of importing to prevent circular import issue /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ const loader = (window as any)['__LOADER']; const result = await withLoadProgress(loader.tryLoad(pathname)); // @ts-ignore if (result?.redirectTo) { // @ts-ignore return loadAndNavigate({ navigate, to: result.redirectTo, origin, options }); } if (result && lastNavigatedPath === to) { if (pathname !== window.location.pathname || search !== window.location.search) { // origin is used to prevent infinite loop when navigating from post message (from wysiwyg) navigate({ pathname, search, hash }, { ...options, state: { origin }, unstable_flushSync: true, } as NavigateOptions & { unstable_flushSync: boolean }); } // @ts-ignore if (result.props?.disableAutoScroll) return; if (hash) { const el = document.getElementById(hash.slice(1)); if (el) { const navbar = getNavbarElement(); const navbarHeight = navbar?.offsetHeight ?? 0; const elementTop = el.getBoundingClientRect().top + window.scrollY; const scrollPosition = elementTop - navbarHeight; window.scrollTo({ top: scrollPosition, behavior: 'smooth' }); } } else { window.scrollTo(0, 0); } } }