| | 'use client' |
| |
|
| | import CONFIG from './config' |
| | import { useEffect } from 'react' |
| | import { Header } from './components/Header' |
| | import { Nav } from './components/Nav' |
| | import { Footer } from './components/Footer' |
| | import { Title } from './components/Title' |
| | import { SideBar } from './components/SideBar' |
| | import { BlogListPage } from './components/BlogListPage' |
| | import { BlogListScroll } from './components/BlogListScroll' |
| | import { useGlobal } from '@/lib/global' |
| | import { ArticleLock } from './components/ArticleLock' |
| | import { ArticleInfo } from './components/ArticleInfo' |
| | import JumpToTopButton from './components/JumpToTopButton' |
| | import NotionPage from '@/components/NotionPage' |
| | import Comment from '@/components/Comment' |
| | import ShareBar from '@/components/ShareBar' |
| | import SearchInput from './components/SearchInput' |
| | import replaceSearchResult from '@/components/Mark' |
| | import { isBrowser } from '@/lib/utils' |
| | import BlogListGroupByDate from './components/BlogListGroupByDate' |
| | import CategoryItem from './components/CategoryItem' |
| | import TagItem from './components/TagItem' |
| | import { useRouter } from 'next/router' |
| | import { Transition } from '@headlessui/react' |
| | import { Style } from './style' |
| | import { siteConfig } from '@/lib/config' |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | const LayoutBase = props => { |
| | const { children } = props |
| | const { onLoading, fullWidth } = useGlobal() |
| | const router = useRouter() |
| | const { category, tag } = props |
| | |
| | |
| | let slotTop = null |
| | if (category) { |
| | slotTop = <div className='pb-12'><i className="mr-1 fas fa-folder-open" />{category}</div> |
| | } else if (tag) { |
| | slotTop = <div className='pb-12'>#{tag}</div> |
| | } else if (props.slotTop) { |
| | slotTop = props.slotTop |
| | } else if (router.route === '/search') { |
| | |
| | slotTop = <div className='pb-12'><SearchInput {...props} /></div> |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | return ( |
| | <div id='theme-example' className='dark:text-gray-300 bg-white dark:bg-black'> |
| | |
| | <Style/> |
| | |
| | {/* 页头 */} |
| | <Header {...props} /> |
| | |
| | {/* 菜单 */} |
| | <Nav {...props} /> |
| | |
| | {/* 主体 */} |
| | <div id='container-inner' className="w-full relative z-10"> |
| | |
| | {/* 标题栏 */} |
| | {fullWidth ? null : <Title {...props} />} |
| | |
| | <div id='container-wrapper' className={(JSON.parse(siteConfig('LAYOUT_SIDEBAR_REVERSE')) ? 'flex-row-reverse' : '') + 'relative container mx-auto justify-center md:flex items-start py-8 px-2'}> |
| | |
| | {/* 内容 */} |
| | <div className={`w-full ${fullWidth ? '' : 'max-w-3xl'} xl:px-14 lg:px-4`}> |
| | <Transition |
| | show={!onLoading} |
| | appear={true} |
| | enter="transition ease-in-out duration-700 transform order-first" |
| | enterFrom="opacity-0 translate-y-16" |
| | enterTo="opacity-100" |
| | leave="transition ease-in-out duration-300 transform" |
| | leaveFrom="opacity-100 translate-y-0" |
| | leaveTo="opacity-0 -translate-y-16" |
| | unmount={false} |
| | > |
| | {/* 嵌入模块 */} |
| | {slotTop} |
| | {children} |
| | </Transition> |
| | </div> |
| | |
| | {/* 侧边栏 */} |
| | {!fullWidth && <SideBar {...props} />} |
| | |
| | </div> |
| | |
| | </div> |
| | |
| | {/* 页脚 */} |
| | <Footer {...props} /> |
| | |
| | {/* 回顶按钮 */} |
| | <div className='fixed right-4 bottom-4 z-10'> |
| | <JumpToTopButton /> |
| | </div> |
| | </div> |
| | ) |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | const LayoutIndex = props => { |
| | return <LayoutPostList {...props} /> |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | const LayoutPostList = props => { |
| | return ( |
| | <> |
| | {siteConfig('POST_LIST_STYLE') === 'page' ? <BlogListPage {...props} /> : <BlogListScroll {...props} />} |
| | </> |
| | ) |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | const LayoutSlug = props => { |
| | const { post, lock, validPassword } = props |
| | return ( |
| | <> |
| | {lock |
| | ? <ArticleLock validPassword={validPassword} /> |
| | : <div id="article-wrapper" className="px-2"> |
| | <ArticleInfo post={post} /> |
| | <NotionPage post={post} /> |
| | <ShareBar post={post} /> |
| | <Comment frontMatter={post} /> |
| | </div>} |
| | </> |
| | ) |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | const Layout404 = (props) => { |
| | return <>404 Not found.</> |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | const LayoutSearch = props => { |
| | const { keyword } = props |
| | const router = useRouter() |
| | useEffect(() => { |
| | if (isBrowser) { |
| | |
| | const container = document.getElementById('posts-wrapper') |
| | if (keyword && container) { |
| | replaceSearchResult({ |
| | doms: container, |
| | search: keyword, |
| | target: { |
| | element: 'span', |
| | className: 'text-red-500 border-b border-dashed' |
| | } |
| | }) |
| | } |
| | } |
| | }, [router]) |
| |
|
| | return <LayoutPostList {...props} /> |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | const LayoutArchive = props => { |
| | const { archivePosts } = props |
| | return (<> |
| | <div className="mb-10 pb-20 md:py-12 p-3 min-h-screen w-full"> |
| | {Object.keys(archivePosts).map(archiveTitle => ( |
| | <BlogListGroupByDate key={archiveTitle} archiveTitle={archiveTitle} archivePosts={archivePosts} /> |
| | ))} |
| | </div> |
| | </>) |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | const LayoutCategoryIndex = props => { |
| | const { categoryOptions } = props |
| | return ( |
| | <> |
| | <div id='category-list' className='duration-200 flex flex-wrap'> |
| | {categoryOptions?.map(category => <CategoryItem key={category.name} category={category} />)} |
| | </div> |
| | </> |
| | ) |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | const LayoutTagIndex = (props) => { |
| | const { tagOptions } = props |
| | return ( |
| | <> |
| | <div id='tags-list' className='duration-200 flex flex-wrap'> |
| | {tagOptions.map(tag => <TagItem key={tag.name} tag={tag} />)} |
| | </div> |
| | </> |
| | ) |
| | } |
| |
|
| | export { |
| | CONFIG as THEME_CONFIG, |
| | LayoutBase, |
| | LayoutIndex, |
| | LayoutPostList, |
| | LayoutSearch, |
| | LayoutArchive, |
| | LayoutSlug, |
| | Layout404, |
| | LayoutCategoryIndex, |
| | LayoutTagIndex |
| | } |
| |
|