forked from primefaces/primereact
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add inline apidoc and some improvement (primefaces#4044)
* generate typedocs * Refactor on api-doc * Added new formatter * Refactor on navbar * Refactor on section nav * Update docsectionnav.js * Refactor * Refactor on doc sections * Update apidoc implementation and improve doc styling * Refactor on menu and docs * Update menu.json --------- Co-authored-by: Cagatay Civici <[email protected]>
- Loading branch information
1 parent
799562d
commit 870b26d
Showing
164 changed files
with
31,837 additions
and
1,053 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
{ | ||
"recommendations": [ | ||
"dbaeumer.vscode-eslint", | ||
"esbenp.prettier-vscode" | ||
"esbenp.prettier-vscode", | ||
"sibiraj-s.vscode-scss-formatter" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,119 +1,104 @@ | ||
import Link from 'next/link'; | ||
import { useRouter } from 'next/router'; | ||
import React, { useEffect, useState } from 'react'; | ||
import { classNames } from '../../lib/utils/Utils'; | ||
import React, { useEffect, useRef, useState } from 'react'; | ||
import { useEventListener } from '../../lib/hooks/Hooks'; | ||
import { classNames, DomHandler, ObjectUtils } from '../../lib/utils/Utils'; | ||
|
||
export function DocSectionNav(props) { | ||
export function DocSectionNav({ docs = [] }) { | ||
const router = useRouter(); | ||
const [activeTab, setActiveTab] = useState(''); | ||
const [activeId, setActiveId] = useState(null); | ||
const navRef = useRef(null); | ||
const topbarHeight = useRef(0); | ||
const isScrollBlocked = useRef(false); | ||
const scrollEndTimer = useRef(undefined); | ||
|
||
const [bindDocumentScrollListener] = useEventListener({ | ||
target: 'window', | ||
type: 'scroll', | ||
listener: (event) => { | ||
if (!isScrollBlocked.current) { | ||
const labels = DomHandler.find(event.target, ':is(h1,h2,h3).doc-section-label'); | ||
const windowScrollTop = DomHandler.getWindowScrollTop(); | ||
|
||
labels.forEach((label) => { | ||
const { top } = DomHandler.getOffset(label); | ||
const threshold = getThreshold(label); | ||
|
||
if (top - threshold <= windowScrollTop) { | ||
const link = DomHandler.findSingle(label, 'a'); | ||
|
||
setActiveId(link.id); | ||
} | ||
}); | ||
} | ||
|
||
const onButtonClick = (doc) => { | ||
// Scroll to the clicked button's parent element | ||
scrollToTheSection(doc.id, 'smooth'); | ||
}; | ||
clearTimeout(scrollEndTimer.current); | ||
scrollEndTimer.current = setTimeout(() => { | ||
isScrollBlocked.current = false; | ||
|
||
const scrollToTheSection = (id, behavior) => { | ||
document.getElementById(id).parentElement.scrollIntoView({ block: 'start', behavior }); | ||
}; | ||
const activeItem = DomHandler.findSingle(navRef.current, '.active-navbar-item'); | ||
|
||
const getIdOfTheSection = (section) => { | ||
return section.querySelector('a').getAttribute('id'); | ||
activeItem && activeItem.scrollIntoView({ block: 'nearest', inline: 'start' }); | ||
}, 50); | ||
} | ||
}); | ||
|
||
const onClick = (id) => { | ||
setActiveId(id); | ||
setTimeout(() => { | ||
scrollToLabelById(id, 'smooth'); | ||
isScrollBlocked.current = true; | ||
}, 1); | ||
}; | ||
|
||
useEffect(() => { | ||
const handleHashChange = (url) => { | ||
const hash = url.split('#')[1]; | ||
|
||
setActiveTab(hash); | ||
}; | ||
const scrollToLabelById = (id, behavior) => { | ||
const label = document.getElementById(id); | ||
|
||
router.events.on('onRouteChangeComplete', handleHashChange); | ||
label && label.parentElement.scrollIntoView({ block: 'start', behavior }); | ||
}; | ||
|
||
return () => { | ||
router.events.off('onRouteChangeComplete', handleHashChange); | ||
}; | ||
}, [props.docs, router.events]); | ||
const getThreshold = (label) => { | ||
if (!topbarHeight.current) { | ||
const topbar = DomHandler.findSingle(document.body, '.layout-topbar'); | ||
|
||
useEffect(() => { | ||
const sections = document.querySelectorAll('section'); // Get all sections on the page | ||
const topbarEl = document.getElementsByClassName('layout-topbar')[0]; // Get the topbar element | ||
const hash = window.location.hash.substring(1); // Get the initial hash | ||
|
||
// Set the active tab to the initial hash and scroll into view if it exists | ||
if (hash) { | ||
setActiveTab(hash); | ||
// Scroll to the section with the current hash | ||
scrollToTheSection(hash); | ||
} else if (window.scrollY + window.innerHeight >= document.body.offsetHeight) { | ||
// Set the active tab to the first section | ||
setActiveTab(getIdOfTheSection(sections[0].querySelector('.doc-section-label'))); | ||
topbarHeight.current = topbar ? DomHandler.getHeight(topbar) : 0; | ||
} | ||
|
||
const onScroll = () => { | ||
sections.forEach((section) => { | ||
const sectionLabelEl = section.querySelectorAll('.doc-section-label'); //Get all labels on the currrent section | ||
// Check if the section is currently scrolled to center of the screen | ||
const isScrolledTo = (section) => window.scrollY >= section.offsetTop - topbarEl.clientHeight - 20 && window.scrollY < section.offsetTop + section.offsetHeight - topbarEl.clientHeight - 20; | ||
|
||
if (isScrolledTo(section)) { | ||
// Check if the section has multiple child elements | ||
if (sectionLabelEl.length > 1) { | ||
sectionLabelEl.forEach((child) => { | ||
// Check if the child element is currently scrolled to | ||
if (isScrolledTo(child)) { | ||
// Set the active tab to the id of the currently scrolled to child element | ||
setActiveTab(getIdOfTheSection(child)); | ||
} | ||
}); | ||
} else { | ||
setActiveTab(getIdOfTheSection(sectionLabelEl[0])); | ||
} | ||
} | ||
}); | ||
}; | ||
|
||
window.addEventListener('scroll', onScroll, { passive: true }); | ||
return topbarHeight.current + DomHandler.getHeight(label) * 1.5; | ||
}; | ||
|
||
return () => { | ||
window.removeEventListener('scroll', onScroll, { passive: true }); | ||
}; | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, []); | ||
useEffect(() => { | ||
const hash = window.location.hash.substring(1); | ||
const hasHash = ObjectUtils.isNotEmpty(hash); | ||
const id = hasHash ? hash : (docs[0] || {}).id; | ||
|
||
setActiveId(id); | ||
hasHash && scrollToLabelById(id); | ||
bindDocumentScrollListener(); | ||
}, []); // eslint-disable-line react-hooks/exhaustive-deps | ||
|
||
const createItem = ({ id, label, children }, level = 0) => { | ||
const { basePath, pathname } = router; | ||
const href = `${basePath}${pathname}#${id}`; | ||
|
||
return ( | ||
<li key={id} className={classNames('navbar-item', { 'active-navbar-item': activeId === id })}> | ||
<div className="navbar-item-content"> | ||
<Link href={href}> | ||
<button className="p-link" onClick={() => onClick(id)} title={label}> | ||
{label} | ||
</button> | ||
</Link> | ||
</div> | ||
|
||
<ul>{level !== 1 && children && children.map((child) => createItem(child, 1))}</ul> | ||
</li> | ||
); | ||
}; | ||
|
||
return ( | ||
<ul className="doc-section-nav"> | ||
{props.docs.map((doc) => { | ||
const hash = doc.id; | ||
|
||
return ( | ||
<React.Fragment key={doc.label}> | ||
<li key={doc.label} className={classNames('navbar-item', { 'active-navbar-item': activeTab === doc.id })}> | ||
<Link href={router.basePath + router.pathname + '#' + hash}> | ||
<button className="p-link" onClick={() => onButtonClick(doc)}> | ||
{doc.label} | ||
</button> | ||
</Link> | ||
</li> | ||
{doc.children && ( | ||
<ul> | ||
{doc.children.map((child) => { | ||
const hash = child.id; | ||
|
||
return ( | ||
<li key={child.label} className={classNames('navbar-child-item', { 'active-navbar-child-item': activeTab === child.id })}> | ||
<Link href={router.basePath + router.pathname + '#' + hash}> | ||
<button className="p-link" onClick={(event) => onButtonClick(child)}> | ||
{child.label} | ||
</button> | ||
</Link> | ||
</li> | ||
); | ||
})} | ||
</ul> | ||
)} | ||
</React.Fragment> | ||
); | ||
})} | ||
<ul ref={navRef} className="doc-section-nav"> | ||
{docs.map((item) => createItem(item))} | ||
</ul> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.