This commit is contained in:
tangly1024.com
2023-03-09 17:59:08 +08:00
parent 42ef2ad566
commit bdedd96853
7 changed files with 106 additions and 10 deletions

View File

@@ -79,7 +79,7 @@ const NotionPage = ({ post, className }) => {
return <>{post?.summary || ''}</>
}
return <div id='container' className={`max-w-5xl font-medium mx-auto ${className}`}>
return <div id='container' className={`font-medium mx-auto ${className}`}>
<NotionRenderer
recordMap={post.blockMap}
mapPageUrl={mapPageUrl}

View File

@@ -48,7 +48,7 @@ const LayoutBase = props => {
</div>
<div className='fixed right-4 bottom-4'>
<div className='fixed right-4 bottom-4 z-20'>
<JumpToTopButton />
</div>

View File

@@ -0,0 +1,92 @@
import React, { useRef } from 'react'
import throttle from 'lodash.throttle'
import { uuidToId } from 'notion-utils'
import { useGlobal } from '@/lib/global'
/**
* 目录导航组件
* @param toc
* @returns {JSX.Element}
* @constructor
*/
const Catalog = ({ post }) => {
const { locale } = useGlobal()
// 监听滚动事件
React.useEffect(() => {
window.addEventListener('scroll', actionSectionScrollSpy)
actionSectionScrollSpy()
return () => {
window.removeEventListener('scroll', actionSectionScrollSpy)
}
}, [])
// 目录自动滚动
const tRef = useRef(null)
const tocIds = []
// 同步选中目录事件
const [activeSection, setActiveSection] = React.useState(null)
const throttleMs = 100
const actionSectionScrollSpy = React.useCallback(throttle(() => {
const sections = document.getElementsByClassName('notion-h')
let prevBBox = null
let currentSectionId = activeSection
for (let i = 0; i < sections.length; ++i) {
const section = sections[i]
if (!section || !(section instanceof Element)) continue
if (!currentSectionId) {
currentSectionId = section.getAttribute('data-id')
}
const bbox = section.getBoundingClientRect()
const prevHeight = prevBBox ? bbox.top - prevBBox.bottom : 0
const offset = Math.max(150, prevHeight / 4)
// GetBoundingClientRect returns values relative to viewport
if (bbox.top - offset < 0) {
currentSectionId = section.getAttribute('data-id')
prevBBox = bbox
continue
}
// No need to continue loop, if last element has been detected
break
}
setActiveSection(currentSectionId)
const index = tocIds.indexOf(currentSectionId) || 0
tRef?.current?.scrollTo({ top: 28 * index, behavior: 'smooth' })
}, throttleMs))
// 无目录就直接返回空
if (!post || !post?.toc || post?.toc?.length < 1) {
return <></>
}
const toc = post.toc
return <div className='px-3 '>
<div className='dark:text-white'><i className='mr-1 fas fa-stream' />{locale.COMMON.TABLE_OF_CONTENTS}</div>
<div className='overflow-y-auto overscroll-none max-h-36 lg:max-h-96 scroll-hidden' ref={tRef}>
<nav className='h-full text-black'>
{toc.map((tocItem) => {
const id = uuidToId(tocItem.id)
tocIds.push(id)
return (
<a
key={id}
href={`#${id}`}
className={`notion-table-of-contents-item duration-300 transform font-light dark:text-gray-200
notion-table-of-contents-item-indent-level-${tocItem.indentLevel} `}
>
<span style={{ display: 'inline-block', marginLeft: tocItem.indentLevel * 16 }}
className={`${activeSection === id && ' font-bold text-red-500 underline overflow-ellipsis truncate'}`}
>
{tocItem.text}
</span>
</a>
)
})}
</nav>
</div>
</div>
}
export default Catalog

View File

@@ -22,7 +22,7 @@ export const CollapseMenu = ({ link }) => {
}
return <>
<div className='w-full px-8 py-3 text-left border-b' onClick={toggleShow} >
<div className='w-full px-8 py-3 text-left border-b dark:bg-hexo-black-gray dark:border-black' onClick={toggleShow} >
{!hasSubMenu && <Link
href={link?.to}
className="font-extralight flex justify-between pl-2 pr-4 dark:text-gray-200 no-underline tracking-widest pb-1">
@@ -39,7 +39,7 @@ export const CollapseMenu = ({ link }) => {
{/* 折叠子菜单 */}
{hasSubMenu && <Collapse isOpen={isOpen}>
{link.subMenus.map(sLink => {
return <div key={sLink.id} className='font-extralight text-left px-10 justify-start text-blue-400 bg-gray-50 hover:bg-gray-50 dark:hover:bg-gray-900 tracking-widest transition-all duration-200 border-b dark:border-gray-800 py-3 pr-6'>
return <div key={sLink.id} className='font-extralight dark:bg-black text-left px-10 justify-start text-blue-400 bg-gray-50 hover:bg-gray-50 dark:hover:bg-gray-900 tracking-widest transition-all duration-200 border-b dark:border-gray-800 py-3 pr-6'>
<Link href={sLink.to}>
<span className='text-xs'>{sLink.title}</span>
</Link>

View File

@@ -11,7 +11,7 @@ export const Footer = (props) => {
return currentYear
})()
return <footer className="z-10 relative w-full bg-black px-6 border-t">
return <footer className="relative w-full bg-black px-6 border-t">
<DarkModeButton className='text-center pt-4'/>
<div className="text-yellow-300 container mx-auto max-w-4xl py-6 md:flex flex-wrap md:flex-no-wrap md:justify-between items-center text-sm">

View File

@@ -61,7 +61,7 @@ export const NavBarMenu = ({ customNav, customMenu }) => {
</div>
<Collapse className='absolute w-full top-12 left-0' isOpen={isOpen}>
<div id='menu-wrap' className='bg-white border'>
<div id='menu-wrap' className='bg-white dark:border-hexo-black-gray border'>
{links?.map(link => {
if (link?.show) {
return <CollapseMenu key={link.id} link={link} />

View File

@@ -1,18 +1,22 @@
import Live2D from '@/components/Live2D'
import Announcement from './Announcement'
import Catalog from './Catalog'
export const SideBar = (props) => {
const { notice } = props
return (
<div className="hidden lg:block flex-none max-w-md sticky top-8 border-l dark:border-gray-800 pl-12 border-gray-100">
<div className="hidden lg:block flex-none sticky top-8 max-w-md border-l dark:border-gray-800 pl-12 border-gray-100">
<aside>
<Announcement post={notice}/>
<aside >
<Catalog {...props} />
</aside>
<aside className=" overflow-hidden mb-6">
<aside className="overflow-hidden mb-6">
<Live2D />
</aside>
<aside>
<Announcement post={notice} />
</aside>
</div>
)