forked from TanStack/query
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathuseTocHighlight.js
83 lines (68 loc) · 2.19 KB
/
useTocHighlight.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
71
72
73
74
75
76
77
78
79
80
81
82
83
import React from 'react'
/**
* Sets up Table of Contents highlighting. It requires that
*/
export function useTocHighlight(
linkClassName,
linkActiveClassName,
topOffset,
getHeaderAnchors,
getHeaderDataFromAnchor,
getAnchorHeaderIdentifier
) {
const [lastActiveLink, setLastActiveLink] = React.useState(undefined)
const [headings, setHeadings] = React.useState([])
React.useEffect(() => {
setHeadings(getHeaderAnchors().map(getHeaderDataFromAnchor))
}, [setHeadings])
React.useEffect(() => {
let headersAnchors = []
let links = []
function setActiveLink() {
function getActiveHeaderAnchor() {
let index = 0
let activeHeaderAnchor = null
headersAnchors = getHeaderAnchors()
while (index < headersAnchors.length && !activeHeaderAnchor) {
const headerAnchor = headersAnchors[index]
const { top } = headerAnchor.getBoundingClientRect()
if (top >= 0 && top <= topOffset) {
activeHeaderAnchor = headerAnchor
}
index += 1
}
return activeHeaderAnchor
}
const activeHeaderAnchor = getActiveHeaderAnchor()
if (activeHeaderAnchor) {
let index = 0
let itemHighlighted = false
links = document.getElementsByClassName(linkClassName)
while (index < links.length && !itemHighlighted) {
const link = links[index]
const { href } = link
const anchorValue = decodeURIComponent(
href.substring(href.indexOf('#') + 1)
)
if (getAnchorHeaderIdentifier(activeHeaderAnchor) === anchorValue) {
if (lastActiveLink) {
lastActiveLink.classList.remove(linkActiveClassName)
}
link.classList.add(linkActiveClassName)
setLastActiveLink(link)
itemHighlighted = true
}
index += 1
}
}
}
document.addEventListener('scroll', setActiveLink)
document.addEventListener('resize', setActiveLink)
setActiveLink()
return () => {
document.removeEventListener('scroll', setActiveLink)
document.removeEventListener('resize', setActiveLink)
}
})
return headings
}