scoll view for toc
This commit is contained in:
+129
-30
@@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useLayoutEffect, useRef, useState } from "react";
|
||||||
|
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
import Markdown from 'react-markdown'
|
import Markdown from 'react-markdown'
|
||||||
@@ -35,6 +35,7 @@ import {
|
|||||||
FileCopy as FileCopyIcon
|
FileCopy as FileCopyIcon
|
||||||
} from "@mui/icons-material";
|
} from "@mui/icons-material";
|
||||||
import { fontGrid } from "@mui/material/styles/cssUtils.js";
|
import { fontGrid } from "@mui/material/styles/cssUtils.js";
|
||||||
|
import { active } from "d3";
|
||||||
|
|
||||||
const Body = {
|
const Body = {
|
||||||
//maxWidth: 1000,
|
//maxWidth: 1000,
|
||||||
@@ -54,17 +55,6 @@ const hrefStyle = {
|
|||||||
textDecoration: "none",
|
textDecoration: "none",
|
||||||
};
|
};
|
||||||
|
|
||||||
const hrefStyleToc = {
|
|
||||||
color: "rgba(255, 255, 255, 0.6)",
|
|
||||||
textDecoration: "none",
|
|
||||||
fontSize: "14px",
|
|
||||||
fontWeight: 400,
|
|
||||||
padding: "4px 0",
|
|
||||||
paddingLeft: "8px",
|
|
||||||
paddingRight: "8px",
|
|
||||||
lineHeight: "20px",
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const hrefStyleToc2 = {
|
const hrefStyleToc2 = {
|
||||||
color: "rgba(255, 255, 255, 0.6)",
|
color: "rgba(255, 255, 255, 0.6)",
|
||||||
@@ -87,8 +77,38 @@ const innerHrefStyle = {
|
|||||||
textDecoration: "none",
|
textDecoration: "none",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Emma Goto
|
||||||
|
const useIntersectionObserver = (setActiveId) => {
|
||||||
|
const headingElementsRef = useRef({})
|
||||||
|
const callback = (headings) => {
|
||||||
|
headingElementsRef.current = headings.reduce((map, headingElemet) => {
|
||||||
|
if (headingElemet.target.id != undefined || headingElemet.target.id != "") {
|
||||||
|
map[headingElemet.target.id] = headingElemet
|
||||||
|
return map
|
||||||
|
}
|
||||||
|
}, headingElementsRef.current)
|
||||||
|
|
||||||
|
const visibleHeadings = [];
|
||||||
|
Object.keys(headingElementsRef.current).forEach((key) => {
|
||||||
|
const headingElemet = headingElementsRef.current[key];
|
||||||
|
if (headingElemet.isIntersecting) visibleHeadings.push(headingElemet)
|
||||||
|
})
|
||||||
|
|
||||||
|
if (visibleHeadings.length > 0) {
|
||||||
|
setActiveId(visibleHeadings[0].target.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const observer = new IntersectionObserver(callback, {
|
||||||
|
rootMargin: "10%",
|
||||||
|
});
|
||||||
|
|
||||||
|
const headingElements = Array.from(document.querySelectorAll("h2"))
|
||||||
|
if (headingElements.length != 0) {
|
||||||
|
headingElements.forEach((element) => observer.observe(element));
|
||||||
|
return () => observer.disconnect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export const CopyToClipboard = (props) => {
|
export const CopyToClipboard = (props) => {
|
||||||
@@ -227,22 +247,18 @@ const Docs = (defaultprops) => {
|
|||||||
props.match = {}
|
props.match = {}
|
||||||
props.match.params = params
|
props.match.params = params
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
//if (params["key"] === undefined) {
|
|
||||||
// navigate("/docs/about")
|
|
||||||
// return
|
|
||||||
//}
|
|
||||||
}, [])
|
|
||||||
//console.log("PARAMS: ", params)
|
//console.log("PARAMS: ", params)
|
||||||
|
|
||||||
const [mobile, setMobile] = useState(serverMobile === true || isMobile === true ? true : false);
|
const [mobile, setMobile] = useState(serverMobile === true || isMobile === true ? true : false);
|
||||||
const [data, setData] = useState("");
|
const [data, setData] = useState("");
|
||||||
const [firstrequest, setFirstrequest] = useState(true);
|
const [firstrequest, setFirstrequest] = useState(true);
|
||||||
const [list, setList] = useState([]);
|
const [list, setList] = useState([]);
|
||||||
|
const [activeId, setActiveId] = useState();
|
||||||
const [isopen, setOpen] = useState(-1);
|
const [isopen, setOpen] = useState(-1);
|
||||||
const [hover, setHover] = useState(false);
|
const [hover, setHover] = useState(false);
|
||||||
const [, setListLoaded] = useState(false);
|
const [, setListLoaded] = useState(false);
|
||||||
const [anchorEl, setAnchorEl] = React.useState(null);
|
const [anchorEl, setAnchorEl] = React.useState(null);
|
||||||
|
const [anchorElToc, setAnchorElToc] = React.useState(null);
|
||||||
const [headingSet, setHeadingSet] = React.useState(false);
|
const [headingSet, setHeadingSet] = React.useState(false);
|
||||||
const [selectedMeta, setSelectedMeta] = React.useState({
|
const [selectedMeta, setSelectedMeta] = React.useState({
|
||||||
link: "hello",
|
link: "hello",
|
||||||
@@ -253,10 +269,23 @@ const Docs = (defaultprops) => {
|
|||||||
serverside === true ? "" : window.location.href
|
serverside === true ? "" : window.location.href
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
//if (params["key"] === undefined) {
|
||||||
|
// navigate("/docs/about")
|
||||||
|
// return
|
||||||
|
//}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
useIntersectionObserver(setActiveId);
|
||||||
|
|
||||||
function handleClick(event) {
|
function handleClick(event) {
|
||||||
setAnchorEl(event.currentTarget);
|
setAnchorEl(event.currentTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleClickToc(event) {
|
||||||
|
setAnchorElToc(event.currentTarget);
|
||||||
|
}
|
||||||
|
|
||||||
function handleCollapse(index) {
|
function handleCollapse(index) {
|
||||||
setOpen(isopen === index ? -1 : index)
|
setOpen(isopen === index ? -1 : index)
|
||||||
}
|
}
|
||||||
@@ -269,6 +298,21 @@ const Docs = (defaultprops) => {
|
|||||||
setAnchorEl(null);
|
setAnchorEl(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleCloseToc() {
|
||||||
|
setAnchorElToc(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrollToHash() {
|
||||||
|
const hash = window.location.hash.replace("#", "")
|
||||||
|
if (hash) {
|
||||||
|
const element = document.getElementById(hash)
|
||||||
|
if (element) {
|
||||||
|
element.scrollIntoView({ behavior: 'smooth' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
function tocvalue(markdown) {
|
function tocvalue(markdown) {
|
||||||
const items = [];
|
const items = [];
|
||||||
let currentMainItem = null;
|
let currentMainItem = null;
|
||||||
@@ -322,7 +366,7 @@ const Docs = (defaultprops) => {
|
|||||||
|
|
||||||
const element = React.createElement(
|
const element = React.createElement(
|
||||||
`h${props.level}`,
|
`h${props.level}`,
|
||||||
{ style: { marginTop: props.level === 1 ? 20 : 50 } },
|
{ style: { marginTop: props.level === 1 ? 20 : 50, scrollPaddingTop: "50px" }, id: `${id}` },
|
||||||
props.children
|
props.children
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -361,8 +405,8 @@ const Docs = (defaultprops) => {
|
|||||||
width: "17%",
|
width: "17%",
|
||||||
position: "sticky",
|
position: "sticky",
|
||||||
top: 50,
|
top: 50,
|
||||||
minHeight: "100vh",
|
minHeight: "93vh",
|
||||||
maxHeight: "100vh",
|
maxHeight: "93vh",
|
||||||
overflowX: "hidden",
|
overflowX: "hidden",
|
||||||
overflowY: "auto",
|
overflowY: "auto",
|
||||||
zIndex: 1000,
|
zIndex: 1000,
|
||||||
@@ -399,6 +443,8 @@ const Docs = (defaultprops) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const fetchDocs = (docId) => {
|
const fetchDocs = (docId) => {
|
||||||
|
setActiveId("")
|
||||||
|
setTocLines([])
|
||||||
fetch(`${globalUrl}/api/v1/docs/${docId}`, {
|
fetch(`${globalUrl}/api/v1/docs/${docId}`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
@@ -571,9 +617,9 @@ const Docs = (defaultprops) => {
|
|||||||
// //$(".parent").find("h2:contains('Statistics')").parent();
|
// //$(".parent").find("h2:contains('Statistics')").parent();
|
||||||
// };
|
// };
|
||||||
|
|
||||||
// if (serverside !== true && window.location.hash.length > 0) {
|
if (serverside !== true && window.location.hash.length > 0) {
|
||||||
// parseElementScroll();
|
scrollToHash()
|
||||||
// }
|
}
|
||||||
|
|
||||||
const markdownStyle = {
|
const markdownStyle = {
|
||||||
color: "rgba(255, 255, 255, 0.90)",
|
color: "rgba(255, 255, 255, 0.90)",
|
||||||
@@ -786,14 +832,27 @@ const Docs = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div style={IndexBar}>
|
<div style={IndexBar}>
|
||||||
<h2 style={{ fontWeight: 600, margin: 0, fontSize: "16px", marginBottom: "8px" }}>Table Of Content</h2>
|
{tocLines.length > 0 ?
|
||||||
|
(
|
||||||
|
<h4 style={{ fontWeight: 600, margin: 0, fontSize: "16px", marginBottom: "8px" }}>Table Of Content</h4>
|
||||||
|
|
||||||
|
) : null}
|
||||||
<nav>
|
<nav>
|
||||||
{tocLines.map((data, index) => {
|
{tocLines.map((data, index) => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className="toc">
|
||||||
<ListItemButton
|
<ListItemButton
|
||||||
key={data.text}
|
key={data.text}
|
||||||
style={hrefStyleToc}
|
style={{
|
||||||
|
color: activeId === data.id ? "#f86a3e" : "inherit",
|
||||||
|
textDecoration: "none",
|
||||||
|
fontSize: "14px",
|
||||||
|
fontWeight: 400,
|
||||||
|
padding: "4px 0",
|
||||||
|
paddingLeft: "8px",
|
||||||
|
paddingRight: "8px",
|
||||||
|
lineHeight: "20px",
|
||||||
|
}}
|
||||||
onClick={() => (
|
onClick={() => (
|
||||||
handleCollapse(index)
|
handleCollapse(index)
|
||||||
)}
|
)}
|
||||||
@@ -804,7 +863,8 @@ const Docs = (defaultprops) => {
|
|||||||
<>{isopen == index ? <ExpandMoreIcon /> : <KeyboardArrowRightIcon />}</>
|
<>{isopen == index ? <ExpandMoreIcon /> : <KeyboardArrowRightIcon />}</>
|
||||||
) : null}
|
) : null}
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
{data.items.length > 0 &&
|
{
|
||||||
|
data.items.length > 0 &&
|
||||||
data.items !== null &&
|
data.items !== null &&
|
||||||
data.items !== undefined ? (
|
data.items !== undefined ? (
|
||||||
<Collapse in={isopen === index} timeout="auto" unmountOnExit>
|
<Collapse in={isopen === index} timeout="auto" unmountOnExit>
|
||||||
@@ -820,7 +880,8 @@ const Docs = (defaultprops) => {
|
|||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</Collapse>
|
</Collapse>
|
||||||
) : null}
|
) : null
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
)
|
)
|
||||||
@@ -841,7 +902,6 @@ const Docs = (defaultprops) => {
|
|||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const postDataMobile =
|
const postDataMobile =
|
||||||
list === undefined || list === null ? null : (
|
list === undefined || list === null ? null : (
|
||||||
<div style={mobileStyle}>
|
<div style={mobileStyle}>
|
||||||
@@ -856,6 +916,14 @@ const Docs = (defaultprops) => {
|
|||||||
>
|
>
|
||||||
<div style={{ color: "white" }}>More docs</div>
|
<div style={{ color: "white" }}>More docs</div>
|
||||||
</Button>
|
</Button>
|
||||||
|
<Menu
|
||||||
|
id="simple-menu"
|
||||||
|
anchorEl={anchorEl}
|
||||||
|
style={{}}
|
||||||
|
keepMounted
|
||||||
|
open={Boolean(anchorEl)}
|
||||||
|
onClose={handleClose}
|
||||||
|
>
|
||||||
{list.map((data, index) => {
|
{list.map((data, index) => {
|
||||||
const item = data.name;
|
const item = data.name;
|
||||||
if (item === undefined) {
|
if (item === undefined) {
|
||||||
@@ -878,6 +946,37 @@ const Docs = (defaultprops) => {
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
</Menu>
|
||||||
|
<Button
|
||||||
|
fullWidth
|
||||||
|
style={{ marginTop: "2px" }}
|
||||||
|
aria-controls="simple-menu"
|
||||||
|
aria-haspopup="ture"
|
||||||
|
variant="outlined"
|
||||||
|
color="primary"
|
||||||
|
onClick={handleClickToc}
|
||||||
|
>
|
||||||
|
<div style={{ color: "white" }}>Table Of Contents</div>
|
||||||
|
</Button>
|
||||||
|
<Menu
|
||||||
|
id="simple-menu"
|
||||||
|
anchorEl={anchorElToc}
|
||||||
|
style={{}}
|
||||||
|
keepMounted
|
||||||
|
open={Boolean(anchorElToc)}
|
||||||
|
onClose={handleCloseToc}
|
||||||
|
>
|
||||||
|
{tocLines.map((data, index) => {
|
||||||
|
return (
|
||||||
|
<MenuItem
|
||||||
|
key={index}
|
||||||
|
style={{ color: "white" }}
|
||||||
|
>
|
||||||
|
<a href={`#${data.id}`} style={hrefStyle}>{data.title}</a>
|
||||||
|
</MenuItem>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</Menu>
|
||||||
</div>
|
</div>
|
||||||
{props.match.params.key === undefined ?
|
{props.match.params.key === undefined ?
|
||||||
mainpageInfo
|
mainpageInfo
|
||||||
|
|||||||
Reference in New Issue
Block a user