Skip to content

Commit

Permalink
website: fix toc scroll issue.
Browse files Browse the repository at this point in the history
  • Loading branch information
jaywcjlove committed Apr 16, 2023
1 parent c2dfc78 commit 8b3602a
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 115 deletions.
89 changes: 89 additions & 0 deletions website/src/components/Preview/Hyperlink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { useEffect } from 'react';
import { useSearchParams } from 'react-router-dom';

export function debounce<T extends any[]>(func: (...args: T) => void, wait: number) {
let timeout: ReturnType<typeof setTimeout>;
return function (...args: T) {
// @ts-ignore
const context = this;
clearTimeout(timeout);
timeout = setTimeout(() => {
func.apply(context, args);
}, wait);
};
}

function scrollTop(offsetTop: number) {
document.documentElement.scrollTo(0, offsetTop);
}

export const Hyperlink = (props: any) => {
const { dom } = props;
let [searchParams, setSearchParams] = useSearchParams();
useEffect(() => {
if (dom) {
const clickFn = (event: MouseEvent) => {
event.preventDefault();
const target = event.currentTarget as HTMLAnchorElement;
const hash = new URL(target.href || '').hash.replace(/^#/, '');
const elm = document.getElementById(decodeURIComponent(hash)) as HTMLHeadingElement;
scrollTop(elm.offsetTop);
searchParams.set('_id', decodeURIComponent(hash));
setSearchParams(searchParams);
if (target.className.indexOf('toc-link') > -1) {
(target.parentElement?.childNodes as unknown as HTMLAnchorElement[]).forEach((item) => {
item.classList.remove('active');
});
target.classList.add('active');
}
};
setTimeout(() => {
const anchor = dom.getElementsByClassName('anchor') as HTMLCollectionOf<HTMLAnchorElement>;
Array.from(anchor).forEach((item) => {
item.onclick = clickFn;
});
const tocAnchor = dom.getElementsByClassName('toc-link') as HTMLCollectionOf<HTMLAnchorElement>;
Array.from(tocAnchor).forEach((item) => {
item.onclick = clickFn;
});
}, 900);
}
}, [dom, searchParams, setSearchParams]);

useEffect(() => {
const scrollEndFn = () => {
const anchor = dom?.getElementsByClassName('anchor') as HTMLCollectionOf<HTMLAnchorElement>;
let hash = '';
Array.from(anchor || []).forEach((item, idx) => {
if (idx === 0) {
hash = new URL(item.href || '').hash.replace(/^#/, '');
}
if (document.documentElement.scrollTop - item.offsetTop > -1) {
hash = new URL(item.href || '').hash.replace(/^#/, '');
}
});

const tocLink = document.querySelector(`a[href="#${decodeURIComponent(hash)}"].toc-link`) as HTMLAnchorElement;
if (tocLink) {
(tocLink.parentElement?.childNodes as unknown as HTMLAnchorElement[]).forEach((item) => {
item.classList.remove('active');
});
tocLink.classList.add('active');
searchParams.set('_id', decodeURIComponent(hash));
setSearchParams(searchParams);
}
const marker = document.querySelector('.menu-marker') as HTMLDivElement;
const tocLinkActive = document.querySelector('.toc-link.active') as HTMLDivElement;
if (tocLinkActive && marker) {
marker.style.top = `${tocLinkActive.offsetTop}px`;
}
};
const scrollEnd = debounce<any>(scrollEndFn, 50);
window.addEventListener('scroll', scrollEnd);
return () => {
window.removeEventListener('scroll', scrollEnd);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [dom]);
return null;
};
4 changes: 2 additions & 2 deletions website/src/components/Preview/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import BackToUp from '@uiw/react-back-to-top';
import { getMetaId, isMeta, getURLParameters } from 'markdown-react-code-preview-loader';
import CodeLayout from 'react-code-preview-layout';
import { useMdData, MdDataHandle } from './useMdData';
import { useHyperlink } from './useHyperlink';
import { getTocTree } from './nodes/toc';
import Footer from '../Footer';
import { Hyperlink } from './Hyperlink';
import './nodes/toc.less';

// @ts-ignore
Expand Down Expand Up @@ -57,10 +57,10 @@ interface PreviewDocumentProps {
const PreviewDocument = ({ path, editor }: PreviewDocumentProps) => {
const $dom = useRef<HTMLDivElement>(null);
const { mdData } = useMdData(path);
useHyperlink($dom.current);
const editorUrl = `https://github.com/uiwjs/react-baidu-map/tree/master/${editor}`;
return (
<Wrapper ref={$dom}>
<Hyperlink dom={$dom.current} />
<Markdown
disableCopy={true}
source={mdData.source}
Expand Down
113 changes: 0 additions & 113 deletions website/src/components/Preview/useHyperlink.tsx

This file was deleted.

0 comments on commit 8b3602a

Please sign in to comment.