mirror of
https://github.com/d0zingcat/nextjs-notion-starter-kit.git
synced 2026-05-13 15:09:47 +00:00
👅
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import React from 'react'
|
||||
import useDarkMode from '@fisch0920/use-dark-mode'
|
||||
import { FaTwitter } from '@react-icons/all-files/fa/FaTwitter'
|
||||
import { FaZhihu } from '@react-icons/all-files/fa/FaZhihu'
|
||||
import { FaGithub } from '@react-icons/all-files/fa/FaGithub'
|
||||
@@ -11,39 +12,31 @@ import styles from './styles.module.css'
|
||||
|
||||
// TODO: merge the data and icons from PageSocial with the social links in Footer
|
||||
|
||||
export const Footer: React.FC<{
|
||||
isDarkMode: boolean
|
||||
toggleDarkMode: () => void
|
||||
}> = ({ isDarkMode, toggleDarkMode }) => {
|
||||
const [hasMounted, setHasMounted] = React.useState(false)
|
||||
const toggleDarkModeCb = React.useCallback(
|
||||
export const FooterImpl: React.FC = () => {
|
||||
const darkMode = useDarkMode(false, { classNameDark: 'dark-mode' })
|
||||
|
||||
const onToggleDarkMode = React.useCallback(
|
||||
(e) => {
|
||||
e.preventDefault()
|
||||
toggleDarkMode()
|
||||
darkMode.toggle()
|
||||
},
|
||||
[toggleDarkMode]
|
||||
[darkMode]
|
||||
)
|
||||
|
||||
React.useEffect(() => {
|
||||
setHasMounted(true)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<footer className={styles.footer}>
|
||||
<div className={styles.copyright}>Copyright 2022 {config.author}</div>
|
||||
|
||||
{hasMounted ? (
|
||||
<div className={styles.settings}>
|
||||
<a
|
||||
className={styles.toggleDarkMode}
|
||||
href='#'
|
||||
onClick={toggleDarkModeCb}
|
||||
title='Toggle dark mode'
|
||||
>
|
||||
{isDarkMode ? <IoMoonSharp /> : <IoSunnyOutline />}
|
||||
</a>
|
||||
</div>
|
||||
) : null}
|
||||
<div className={styles.settings}>
|
||||
<a
|
||||
className={styles.toggleDarkMode}
|
||||
href='#'
|
||||
role='button'
|
||||
onClick={onToggleDarkMode}
|
||||
>
|
||||
{darkMode.value ? <IoMoonSharp /> : <IoSunnyOutline />}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div className={styles.social}>
|
||||
{config.twitter && (
|
||||
@@ -97,3 +90,5 @@ export const Footer: React.FC<{
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
|
||||
export const Footer = React.memo(FooterImpl)
|
||||
|
||||
@@ -58,7 +58,11 @@ const Pdf = dynamic(
|
||||
}
|
||||
)
|
||||
const Modal = dynamic(
|
||||
() => import('react-notion-x/build/third-party/modal').then((m) => m.Modal),
|
||||
() =>
|
||||
import('react-notion-x/build/third-party/modal').then((m) => {
|
||||
m.Modal.setAppElement('.notion-viewport')
|
||||
return m.Modal
|
||||
}),
|
||||
{
|
||||
ssr: false
|
||||
}
|
||||
@@ -73,15 +77,48 @@ export const NotionPage: React.FC<types.PageProps> = ({
|
||||
const router = useRouter()
|
||||
const lite = useSearchParam('lite')
|
||||
|
||||
const params: any = {}
|
||||
if (lite) params.lite = lite
|
||||
const components = React.useMemo(
|
||||
() => ({
|
||||
nextImage: Image,
|
||||
nextLink: Link,
|
||||
Code,
|
||||
Collection,
|
||||
Equation,
|
||||
Pdf,
|
||||
Modal,
|
||||
Tweet,
|
||||
Header: NotionPageHeader
|
||||
}),
|
||||
[]
|
||||
)
|
||||
|
||||
const twitterContextValue = React.useMemo(() => {
|
||||
if (!recordMap) {
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
tweetAstMap: (recordMap as any).tweetAstMap || {},
|
||||
swrOptions: {
|
||||
fetcher: (id: string) =>
|
||||
fetch(`/api/get-tweet-ast/${id}`).then((r) => r.json())
|
||||
}
|
||||
}
|
||||
}, [recordMap])
|
||||
|
||||
// lite mode is for oembed
|
||||
const isLiteMode = lite === 'true'
|
||||
const searchParams = new URLSearchParams(params)
|
||||
|
||||
const darkMode = useDarkMode(false, { classNameDark: 'dark-mode' })
|
||||
|
||||
const siteMapPageUrl = React.useMemo(() => {
|
||||
const params: any = {}
|
||||
if (lite) params.lite = lite
|
||||
|
||||
const searchParams = new URLSearchParams(params)
|
||||
return mapPageUrl(site, recordMap, searchParams)
|
||||
}, [site, recordMap, lite])
|
||||
|
||||
if (router.isFallback) {
|
||||
return <Loading />
|
||||
}
|
||||
@@ -111,8 +148,6 @@ export const NotionPage: React.FC<types.PageProps> = ({
|
||||
g.block = block
|
||||
}
|
||||
|
||||
const siteMapPageUrl = mapPageUrl(site, recordMap, searchParams)
|
||||
|
||||
const canonicalPageUrl =
|
||||
!config.isDev && getCanonicalPageUrl(site, recordMap)(pageId)
|
||||
|
||||
@@ -147,15 +182,7 @@ export const NotionPage: React.FC<types.PageProps> = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<TwitterContextProvider
|
||||
value={{
|
||||
tweetAstMap: (recordMap as any).tweetAstMap || {},
|
||||
swrOptions: {
|
||||
fetcher: (id) =>
|
||||
fetch(`/api/get-tweet-ast/${id}`).then((r) => r.json())
|
||||
}
|
||||
}}
|
||||
>
|
||||
<TwitterContextProvider value={twitterContextValue}>
|
||||
<PageHead
|
||||
pageId={pageId}
|
||||
site={site}
|
||||
@@ -174,17 +201,7 @@ export const NotionPage: React.FC<types.PageProps> = ({
|
||||
styles.notion,
|
||||
pageId === site.rootNotionPageId && 'index-page'
|
||||
)}
|
||||
components={{
|
||||
nextImage: Image,
|
||||
nextLink: Link,
|
||||
Code,
|
||||
Collection,
|
||||
Equation,
|
||||
Pdf,
|
||||
Modal,
|
||||
Tweet,
|
||||
Header: NotionPageHeader
|
||||
}}
|
||||
components={components}
|
||||
recordMap={recordMap}
|
||||
rootPageId={site.rootNotionPageId}
|
||||
rootDomain={site.domain}
|
||||
@@ -199,14 +216,9 @@ export const NotionPage: React.FC<types.PageProps> = ({
|
||||
defaultPageCoverPosition={config.defaultPageCoverPosition}
|
||||
mapPageUrl={siteMapPageUrl}
|
||||
mapImageUrl={mapImageUrl}
|
||||
searchNotion={searchNotion}
|
||||
searchNotion={config.isSearchEnabled ? searchNotion : null}
|
||||
pageAside={pageAside}
|
||||
footer={
|
||||
<Footer
|
||||
isDarkMode={darkMode.value}
|
||||
toggleDarkMode={darkMode.toggle}
|
||||
/>
|
||||
}
|
||||
footer={<Footer />}
|
||||
/>
|
||||
|
||||
<GitHubShareButton />
|
||||
|
||||
@@ -1,16 +1,27 @@
|
||||
import React from 'react'
|
||||
// import useDarkMode from '@fisch0920/use-dark-mode'
|
||||
import cs from 'classnames'
|
||||
import useDarkMode from '@fisch0920/use-dark-mode'
|
||||
import { IoSunnyOutline } from '@react-icons/all-files/io5/IoSunnyOutline'
|
||||
import { IoMoonSharp } from '@react-icons/all-files/io5/IoMoonSharp'
|
||||
|
||||
import { Header, Breadcrumbs, Search } from 'react-notion-x'
|
||||
import { Header, Breadcrumbs, Search, useNotionContext } from 'react-notion-x'
|
||||
|
||||
import * as types from 'lib/types'
|
||||
import { navigationStyle } from 'lib/config'
|
||||
import { navigationStyle, navigationLinks, isSearchEnabled } from 'lib/config'
|
||||
|
||||
// import styles from './styles.module.css'
|
||||
import styles from './styles.module.css'
|
||||
|
||||
export const NotionPageHeader: React.FC<{
|
||||
block: types.CollectionViewPageBlock | types.PageBlock
|
||||
}> = ({ block }) => {
|
||||
const darkMode = useDarkMode(false, { classNameDark: 'dark-mode' })
|
||||
const [hasMounted, setHasMounted] = React.useState(false)
|
||||
const { components, mapPageUrl } = useNotionContext()
|
||||
|
||||
React.useEffect(() => {
|
||||
setHasMounted(true)
|
||||
}, [])
|
||||
|
||||
if (navigationStyle === 'default') {
|
||||
return <Header block={block} />
|
||||
}
|
||||
@@ -19,7 +30,52 @@ export const NotionPageHeader: React.FC<{
|
||||
<header className='notion-header'>
|
||||
<div className='notion-nav-header'>
|
||||
<Breadcrumbs block={block} rootOnly={true} />
|
||||
<Search block={block} />
|
||||
|
||||
<div className='notion-nav-header-rhs breadcrumbs'>
|
||||
{navigationLinks
|
||||
?.map((link, index) => {
|
||||
if (!link.pageId && !link.url) {
|
||||
return null
|
||||
}
|
||||
|
||||
if (link.pageId) {
|
||||
return (
|
||||
<components.PageLink
|
||||
href={mapPageUrl(link.pageId)}
|
||||
key={index}
|
||||
className={cs(styles.navLink, 'breadcrumb', 'button')}
|
||||
>
|
||||
{link.title}
|
||||
</components.PageLink>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<components.Link
|
||||
href={link.url}
|
||||
key={index}
|
||||
className={cs(styles.navLink, 'breadcrumb', 'button')}
|
||||
>
|
||||
{link.title}
|
||||
</components.Link>
|
||||
)
|
||||
}
|
||||
})
|
||||
.filter(Boolean)}
|
||||
|
||||
<div
|
||||
className={cs('breadcrumb', 'button')}
|
||||
role='button'
|
||||
onClick={darkMode.toggle}
|
||||
>
|
||||
{hasMounted && darkMode.value ? (
|
||||
<IoMoonSharp />
|
||||
) : (
|
||||
<IoSunnyOutline />
|
||||
)}
|
||||
</div>
|
||||
|
||||
{isSearchEnabled && <Search block={block} title={null} />}
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user