forked from orval-labs/orval
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Toc.js
70 lines (66 loc) · 1.85 KB
/
Toc.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import cx from 'classnames';
import * as React from 'react';
import styles from './Toc.module.css';
import { useTocHighlight } from './useTocHighlight';
const TOP_OFFSET = 100;
function getHeaderAnchors() {
return [
...document.getElementsByTagName('H1'),
...[...document.getElementsByClassName('anchor')].filter(
(el) =>
el.parentNode.nodeName === 'H2' ||
el.parentNode.nodeName === 'H3' ||
el.parentNode.nodeName === 'H4' ||
el.parentNode.nodeName === 'H5',
),
].filter(Boolean);
}
function getHeaderDataFromAnchors(el) {
return {
url: el.getAttribute('href'),
text: el.parentElement?.innerText,
depth: Number(el.parentElement?.nodeName.replace('H', '')),
};
}
export const Toc = ({ title }) => {
const { headings, active } = useTocHighlight(
styles.contents__link,
styles['contents__link--active'],
TOP_OFFSET,
getHeaderAnchors,
getHeaderDataFromAnchors,
(el) => el?.parentElement?.id,
);
return (
<ul className="space-y-3">
<li className="text-sm">
<a className={styles.contents__link} href="#_top">
{title}
</a>
</li>
{headings &&
headings.length > 0 &&
headings.map((h, i) =>
h.url ? (
<li
key={`heading-${h.url}-${i}`}
className={cx('text-sm ', {
'pl-2': h?.depth === 3,
'pl-4': h?.depth === 4,
'pl-6': h?.depth === 5,
hidden:
h.depth &&
h.depth > 3 &&
active?.parent?.url !== h.parent?.url &&
active?.url !== h.parent?.url,
})}
>
<a className={styles.contents__link} href={h.url}>
{h.text}
</a>
</li>
) : null,
)}
</ul>
);
};