blank-theme-with-daisy

This commit is contained in:
tangly1024
2023-06-30 23:24:55 +08:00
parent 8103e23aac
commit aac5eac0fc
18 changed files with 326 additions and 19 deletions

View File

@@ -2,7 +2,7 @@ import BLOG from '@/blog.config'
import { useEffect, useState } from 'react'
import Select from './Select'
import { useGlobal } from '@/lib/global'
import { ALL_THEME } from '@/themes/theme'
import { THEMES } from '@/themes/theme'
import { useRouter } from 'next/router'
/**
@@ -16,7 +16,7 @@ const DebugPanel = () => {
const [siteConfig, updateSiteConfig] = useState({})
// 主题下拉框
const themeOptions = ALL_THEME.map(t => ({ value: t, text: t }))
const themeOptions = THEMES.map(t => ({ value: t, text: t }))
useEffect(() => {
updateSiteConfig(Object.assign({}, BLOG))

View File

@@ -1,7 +1,7 @@
import { useGlobal } from '@/lib/global'
import React from 'react'
import { Draggable } from './Draggable'
import { ALL_THEME } from '@/themes/theme'
import { THEMES } from '@/themes/theme'
import { useRouter } from 'next/router'
/**
*
@@ -27,7 +27,7 @@ const ThemeSwitch = () => {
<i className='fas fa-arrows cursor-move px-2' />
{/* <div className='uppercase font-sans whitespace-nowrap cursor-pointer ' onClick={switchTheme}> {theme}</div> */}
<select value={theme} onChange={onSelectChange} name="cars" className='text-white bg-black uppercase cursor-pointer'>
{ALL_THEME.map(t => {
{THEMES.map(t => {
return <option key={t} value={t}>{t}</option>
})}
</select>

View File

@@ -2,7 +2,7 @@ import { generateLocaleDict, initLocale } from './lang'
import { createContext, useContext, useEffect, useState } from 'react'
import { useRouter } from 'next/router'
import BLOG from '@/blog.config'
import { ALL_THEME, initDarkMode } from '@/themes/theme'
import { THEMES, initDarkMode } from '@/themes/theme'
import NProgress from 'nprogress'
import { getQueryVariable, isBrowser } from './utils'
@@ -69,9 +69,9 @@ export function GlobalContextProvider({ children }) {
// 切换主题
function switchTheme() {
const currentIndex = ALL_THEME.indexOf(theme)
const newIndex = currentIndex < ALL_THEME.length - 1 ? currentIndex + 1 : 0
const newTheme = ALL_THEME[newIndex]
const currentIndex = THEMES.indexOf(theme)
const newIndex = currentIndex < THEMES.length - 1 ? currentIndex + 1 : 0
const newTheme = THEMES[newIndex]
const query = { ...router.query, theme: newTheme }
router.push({ pathname: router.pathname, query })
return newTheme

View File

@@ -3,8 +3,30 @@ const withBundleAnalyzer = require('@next/bundle-analyzer')({
})
const { THEME } = require('./blog.config')
const fs = require('fs')
const path = require('path')
/**
* 扫描指定目录下的文件夹名,用于获取当前有几个主题
* @param {*} directory
* @returns
*/
function scanSubdirectories(directory) {
const subdirectories = []
fs.readdirSync(directory).forEach(file => {
const fullPath = path.join(directory, file)
const stats = fs.statSync(fullPath)
if (stats.isDirectory()) {
subdirectories.push(file)
}
})
return subdirectories
}
// 扫描项目 /themes下的目录名
const themes = scanSubdirectories(path.resolve(__dirname, 'themes'))
module.exports = withBundleAnalyzer({
images: {
// 图片压缩
@@ -68,10 +90,12 @@ module.exports = withBundleAnalyzer({
// })
// }
// console.log(path.resolve(__dirname, 'themes', THEME))
// 动态主题:添加 resolve.alias 配置,将动态路径映射到实际路径
config.resolve.alias['@theme-components'] = path.resolve(__dirname, 'themes', THEME)
return config
},
publicRuntimeConfig: { // 这里的配置既可以服务端获取到,也可以在浏览器端获取到
NODE_ENV_API: process.env.NODE_ENV_API || 'prod',
THEMES: themes
}
})

View File

@@ -29,6 +29,7 @@
"aos": "^3.0.0-beta.6",
"axios": ">=0.21.1",
"copy-to-clipboard": "^3.3.1",
"daisyui": "^3.1.7",
"eslint-plugin-react-hooks": "^4.6.0",
"feed": "^4.2.2",
"js-md5": "^0.7.3",

View File

@@ -29,5 +29,5 @@ module.exports = {
variants: {
extend: {}
},
plugins: []
plugins: [require('daisyui')]
}

View File

@@ -0,0 +1,28 @@
/* eslint-disable @next/next/no-img-element */
const Carousel = () => {
return <div className="carousel carousel-center rounded-box">
<div className="carousel-item">
<img src="https://daisyui.com//images/stock/photo-1559703248-dcaaec9fab78.jpg" alt="Pizza" />
</div>
<div className="carousel-item">
<img src="https://daisyui.com//images/stock/photo-1565098772267-60af42b81ef2.jpg" alt="Pizza" />
</div>
<div className="carousel-item">
<img src="https://daisyui.com//images/stock/photo-1572635148818-ef6fd45eb394.jpg" alt="Pizza" />
</div>
<div className="carousel-item">
<img src="https://daisyui.com//images/stock/photo-1494253109108-2e30c049369b.jpg" alt="Pizza" />
</div>
<div className="carousel-item">
<img src="https://daisyui.com//images/stock/photo-1550258987-190a2d41a8ba.jpg" alt="Pizza" />
</div>
<div className="carousel-item">
<img src="https://daisyui.com//images/stock/photo-1559181567-c3190ca9959b.jpg" alt="Pizza" />
</div>
<div className="carousel-item">
<img src="https://daisyui.com//images/stock/photo-1601004890684-d8cbf643f5f2.jpg" alt="Pizza" />
</div>
</div>
}
export default Carousel

View File

@@ -0,0 +1,28 @@
/* eslint-disable react/no-unescaped-entities */
const ChatBubble = () => {
return <>
<div className="chat chat-start">
<div className="chat-bubble chat-bubble-primary">What kind of nonsense is this</div>
</div>
<div className="chat chat-start">
<div className="chat-bubble chat-bubble-secondary">Put me on the Council and not make me a Master!??</div>
</div>
<div className="chat chat-start">
<div className="chat-bubble chat-bubble-accent">That's never been done in the history of the Jedi. It's insulting!</div>
</div>
<div className="chat chat-end">
<div className="chat-bubble chat-bubble-info">Calm down, Anakin.</div>
</div>
<div className="chat chat-end">
<div className="chat-bubble chat-bubble-success">You have been given a great honor.</div>
</div>
<div className="chat chat-end">
<div className="chat-bubble chat-bubble-warning">To be on the Council at your age.</div>
</div>
<div className="chat chat-end">
<div className="chat-bubble chat-bubble-error">It's never happened before.</div>
</div>
</>
}
export default ChatBubble

View File

@@ -0,0 +1,7 @@
const Divider = () => {
return <div className="flex flex-col w-full border-opacity-50">
<div className="divider"></div>
</div>
}
export default Divider

View File

@@ -0,0 +1,10 @@
const DropDownMenu = () => {
return <details className="dropdown mb-32">
<summary className="m-1 btn">open or close</summary>
<ul className="p-2 shadow menu dropdown-content z-[1] bg-base-100 rounded-box w-52">
<li><a>Item 1</a></li>
<li><a>Item 2</a></li>
</ul>
</details>
}
export default DropDownMenu

View File

@@ -0,0 +1,38 @@
const Footer = () => {
return <footer className="footer p-10 bg-base-200 text-base-content">
<div>
<span className="footer-title">Services</span>
<a className="link link-hover">Branding</a>
<a className="link link-hover">Design</a>
<a className="link link-hover">Marketing</a>
<a className="link link-hover">Advertisement</a>
</div>
<div>
<span className="footer-title">Company</span>
<a className="link link-hover">About us</a>
<a className="link link-hover">Contact</a>
<a className="link link-hover">Jobs</a>
<a className="link link-hover">Press kit</a>
</div>
<div>
<span className="footer-title">Legal</span>
<a className="link link-hover">Terms of use</a>
<a className="link link-hover">Privacy policy</a>
<a className="link link-hover">Cookie policy</a>
</div>
<div>
<span className="footer-title">Newsletter</span>
<div className="form-control w-80">
<label className="label">
<span className="label-text">Enter your email address</span>
</label>
<div className="relative">
<input type="text" placeholder="username@site.com" className="input input-bordered w-full pr-16" />
<button className="btn btn-primary absolute top-0 right-0 rounded-l-none">Subscribe</button>
</div>
</div>
</div>
</footer>
}
export default Footer

View File

@@ -0,0 +1,13 @@
const Hero = () => {
return <div className="hero min-h-screen bg-base-200">
<div className="hero-content text-center">
<div className="max-w-md">
<h1 className="text-5xl font-bold">Hello there</h1>
<p className="py-6">Provident cupiditate voluptatem et in. Quaerat fugiat ut assumenda excepturi exercitationem quasi. In deleniti eaque aut repudiandae et a id nisi.</p>
<button className="btn btn-primary">Get Started</button>
</div>
</div>
</div>
}
export default Hero

View File

@@ -0,0 +1,15 @@
const HeroWithFigure = () => {
return <div className="hero min-h-screen bg-base-200">
<div className="hero-content flex-col lg:flex-row">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img src="/avatar.png" className="max-w-sm rounded-lg shadow-2xl" />
<div>
<h1 className="text-5xl font-bold">Box Office News!</h1>
<p className="py-6">Provident cupiditate voluptatem et in. Quaerat fugiat ut assumenda excepturi exercitationem quasi. In deleniti eaque aut repudiandae et a id nisi.</p>
<button className="btn btn-primary">Get Started</button>
</div>
</div>
</div>
}
export default HeroWithFigure

View File

@@ -0,0 +1,34 @@
const HeroWithForm = () => {
return <div className="hero min-h-screen bg-base-200">
<div className="hero-content flex-col lg:flex-row-reverse">
<div className="text-center lg:text-left">
<h1 className="text-5xl font-bold">Login now!</h1>
<p className="py-6">Provident cupiditate voluptatem et in. Quaerat fugiat ut assumenda excepturi exercitationem quasi. In deleniti eaque aut repudiandae et a id nisi.</p>
</div>
<div className="card flex-shrink-0 w-full max-w-sm shadow-2xl bg-base-100">
<div className="card-body">
<div className="form-control">
<label className="label">
<span className="label-text">Email</span>
</label>
<input type="text" placeholder="email" className="input input-bordered" />
</div>
<div className="form-control">
<label className="label">
<span className="label-text">Password</span>
</label>
<input type="text" placeholder="password" className="input input-bordered" />
<label className="label">
<a href="#" className="label-text-alt link link-hover">Forgot password?</a>
</label>
</div>
<div className="form-control mt-6">
<button className="btn btn-primary">Login</button>
</div>
</div>
</div>
</div>
</div>
}
export default HeroWithForm

View File

@@ -0,0 +1,19 @@
const HeroWithImage = () => {
return <div
className="hero min-h-screen"
style={{ backgroundImage: 'url(https://daisyui.com/images/stock/photo-1507358522600-9f71e620c44e.jpg)' }}
>
<div className="hero-overlay bg-opacity-60"></div>
<div className="hero-content text-center text-neutral-content">
<div className="max-w-md">
<h1 className="mb-5 text-5xl font-bold">Hello there</h1>
<p className="mb-5">
Provident cupiditate voluptatem et in. Quaerat fugiat ut assumenda excepturi exercitationem quasi. In deleniti eaque aut repudiandae et a id nisi.
</p>
<button className="btn btn-primary">Get Started</button>
</div>
</div>
</div>
}
export default HeroWithImage

View File

@@ -0,0 +1,31 @@
const NavBar = () => <div className="drawer">
<input id="my-drawer-3" type="checkbox" className="drawer-toggle" />
<div className="drawer-content flex flex-col">
{/* Navbar */}
<div className="w-full navbar bg-base-300 fixed top-0">
<div className="flex-none lg:hidden">
<label htmlFor="my-drawer-3" className="btn btn-square btn-ghost">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" className="inline-block w-6 h-6 stroke-current"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M4 6h16M4 12h16M4 18h16"></path></svg>
</label>
</div>
<div className="flex-1 px-2 mx-2">Navbar Title</div>
<div className="flex-none hidden lg:block">
<ul className="menu menu-horizontal">
{/* Navbar menu content here */}
<li><a>Navbar Item 1</a></li>
<li><a>Navbar Item 2</a></li>
</ul>
</div>
</div>
</div>
<div className="drawer-side">
<label htmlFor="my-drawer-3" className="drawer-overlay"></label>
<ul className="menu p-4 w-80 h-full bg-base-200">
{/* Sidebar content here */}
<li><a>Sidebar Item 1</a></li>
<li><a>Sidebar Item 2</a></li>
</ul>
</div>
</div>
export default NavBar

64
themes/blank/index.js Normal file
View File

@@ -0,0 +1,64 @@
import NavBar from './components/NavBar'
import Hero from './components/Hero'
import Footer from './components/Footer'
import Divider from './components/Divider'
import HeroWithFigure from './components/HeroWithFigure'
import HeroWithForm from './components/HeroWithForm'
import HeroWithImage from './components/HeroWithImage'
import Carousel from './components/Carousel'
import ChatBubble from './components/ChatBubble'
/**
* 这是一个空白主题的示例
*/
const THEME_CONFIG = { THEME: 'blank' }
/**
* 主题框架
* @param {*} props
* @returns
*/
const LayoutBase = (props) => {
const { children } = props
console.log('children', children)
return <div id='theme-blank'>
<NavBar />
{children}
<Footer />
</div>
}
const LayoutIndex = (props) => {
console.log('首页')
return <LayoutBase {...props}>
<Hero />
<HeroWithFigure />
<HeroWithImage />
<Carousel/>
<ChatBubble/>
<HeroWithForm />
<Divider />
</LayoutBase>
}
const LayoutSearch = () => <></>
const LayoutArchive = () => <></>
const LayoutSlug = () => <></>
const Layout404 = () => <></>
const LayoutCategory = () => <></>
const LayoutCategoryIndex = () => <></>
const LayoutPage = () => <></>
const LayoutTag = () => <></>
const LayoutTagIndex = () => <></>
export {
THEME_CONFIG,
LayoutIndex,
LayoutSearch,
LayoutArchive,
LayoutSlug,
Layout404,
LayoutCategory,
LayoutCategoryIndex,
LayoutPage,
LayoutTag,
LayoutTagIndex
}

View File

@@ -2,15 +2,10 @@ import cookie from 'react-cookies'
import BLOG from '@/blog.config'
import { getQueryParam, getQueryVariable } from '../lib/utils'
import dynamic from 'next/dynamic'
// 使用 __THEME__ 变量来动态导入主题组件
import getConfig from 'next/config'
import * as ThemeComponents from '@theme-components'
/**
* 所有主题枚举
*/
export const ALL_THEME = [
'hexo', 'matery', 'next', 'medium', 'fukasawa', 'nobelium', 'example', 'simple', 'gitbook'
]
// 所有主题在next.config.js中扫描
export const { THEMES = [] } = getConfig().publicRuntimeConfig
/**
* 加载主题文件
* 如果是