diff --git a/.env.local b/.env.local index f2bfdd65..b24ee712 100644 --- a/.env.local +++ b/.env.local @@ -1,2 +1,2 @@ # 环境变量 @see https://www.nextjs.cn/docs/basic-features/environment-variables -NEXT_PUBLIC_VERSION=3.3.4 \ No newline at end of file +NEXT_PUBLIC_VERSION=3.3.5 \ No newline at end of file diff --git a/components/Collapse.js b/components/Collapse.js new file mode 100644 index 00000000..798e2b86 --- /dev/null +++ b/components/Collapse.js @@ -0,0 +1,74 @@ +import React from 'react' + +/** + * 折叠面板组件,支持水平折叠、垂直折叠 + * @param {type:['horizontal','vertical'],isOpen} props + * @returns + */ +const Collapse = props => { + const collapseRef = React.useRef(null) + const type = props.type || 'vertical' + const collapseSection = element => { + const sectionHeight = element.scrollHeight + const sectionWidth = element.scrollWidth + + requestAnimationFrame(function () { + switch (type) { + case 'horizontal': + element.style.width = sectionWidth + 'px' + requestAnimationFrame(function () { + element.style.width = 0 + 'px' + }) + break + case 'vertical': + element.style.height = sectionHeight + 'px' + requestAnimationFrame(function () { + element.style.height = 0 + 'px' + }) + } + }) + } + + /** + * 展开 + * @param {*} element + */ + const expandSection = element => { + const sectionHeight = element.scrollHeight + const sectionWidth = element.scrollWidth + let clearTime = 0 + switch (type) { + case 'horizontal': + element.style.width = sectionWidth + 'px' + clearTime = setTimeout(() => { + element.style.width = 'auto' + }, 400) + break + case 'vertical': + element.style.height = sectionHeight + 'px' + clearTime = setTimeout(() => { + element.style.height = 'auto' + }, 400) + } + + clearTimeout(clearTime) + } + + React.useEffect(() => { + const element = collapseRef.current + if (props.isOpen) { + expandSection(element) + } else { + collapseSection(element) + } + }, [props.isOpen]) + + return ( +
+ {props.children} +
+ ) +} +Collapse.defaultProps = { isOpen: false } + +export default Collapse diff --git a/components/CollapseLeft.js b/components/CollapseLeft.js deleted file mode 100644 index 56d86525..00000000 --- a/components/CollapseLeft.js +++ /dev/null @@ -1,38 +0,0 @@ -import React, { useEffect, useRef } from 'react' - -const Collapse = props => { - const collapseRef = useRef(null) - const collapseSection = element => { - const sectionWidth = element.scrollWidth - requestAnimationFrame(function () { - element.style.width = sectionWidth + 'px' - requestAnimationFrame(function () { - element.style.width = 0 + 'px' - }) - }) - } - const expandSection = element => { - const sectionWidth = element.scrollWidth - element.style.width = sectionWidth + 'px' - const clearTime = setTimeout(() => { - element.style.width = 'auto' - }, 400) - clearTimeout(clearTime) - } - useEffect(() => { - const element = collapseRef.current - if (props.isOpen) { - expandSection(element) - } else { - collapseSection(element) - } - }, [props.isOpen]) - return ( -
- {props.children} -
- ) -} -Collapse.defaultProps = { isOpen: false } - -export default Collapse diff --git a/components/DarkModeButton.js b/components/DarkModeButton.js new file mode 100644 index 00000000..a4d36989 --- /dev/null +++ b/components/DarkModeButton.js @@ -0,0 +1,21 @@ +import { useGlobal } from '@/lib/global' +import { saveDarkModeToCookies } from '@/lib/theme' + +const DarkModeButton = (props) => { + const { isDarkMode, updateDarkMode } = useGlobal() + // 用户手动设置主题 + const handleChangeDarkMode = () => { + const newStatus = !isDarkMode + saveDarkModeToCookies(newStatus) + updateDarkMode(newStatus) + const htmlElement = document.getElementsByTagName('html')[0] + htmlElement.classList?.remove(newStatus ? 'light' : 'dark') + htmlElement.classList?.add(newStatus ? 'dark' : 'light') + } + + return
+ +
+} +export default DarkModeButton diff --git a/components/Draggable.js b/components/Draggable.js new file mode 100644 index 00000000..01d8a553 --- /dev/null +++ b/components/Draggable.js @@ -0,0 +1,138 @@ +import React from 'react' +/** + * 可拖拽组件 + */ + +export const Draggable = (props) => { + const { children } = props + let currentObj, offsetX, offsetY// 初始化变量,定义备用变量 + + React.useEffect(() => { + const draggableElements = document.getElementsByClassName('draggable') + + // 标准化鼠标事件对象 + function e(event) { // 定义事件对象标准化函数 + if (!event) { // 兼容IE浏览器 + event = window.event + event.target = event.srcElement + event.layerX = event.offsetX + event.layerY = event.offsetY + } + // 移动端 + if (event.type === 'touchstart' || event.type === 'touchmove') { + event.clientX = event.touches[0].clientX + event.clientY = event.touches[0].clientY + } + + event.mx = event.pageX || event.clientX + document.body.scrollLeft + // 计算鼠标指针的x轴距离 + event.my = event.pageY || event.clientY + document.body.scrollTop + // 计算鼠标指针的y轴距离 + + return event // 返回标准化的事件对象 + } + + // 定义鼠标事件处理函数 + // document.pointerdown = start + document.onmousedown = start + document.ontouchstart = start + + function start (event) { // 按下鼠标时,初始化处理 + if (!draggableElements) return + event = e(event)// 获取标准事件对象 + + for (const drag of draggableElements) { + // 判断鼠标点击的区域是否是拖拽框内 + if (inDragBox(event, drag)) { + currentObj = drag.firstElementChild + } + } + if (currentObj) { + if (event.type === 'touchstart') { + document.documentElement.style.overflow = 'hidden' // 防止页面一起滚动 + } + offsetX = event.mx - currentObj.offsetLeft + offsetY = event.my - currentObj.offsetTop + + document.onmousemove = move// 注册鼠标移动事件处理函数 + document.ontouchmove = move + document.onmouseup = stop// 注册松开鼠标事件处理函数 + document.ontouchend = stop + } + } + + function move(event) { // 鼠标移动处理函数 + event = e(event) + if (currentObj) { + const left = event.mx - offsetX// 定义拖动元素的x轴距离 + const top = event.my - offsetY// 定义拖动元素的y轴距离 + currentObj.style.left = left + 'px'// 定义拖动元素的x轴距离 + currentObj.style.top = top + 'px'// 定义拖动元素的y轴距离 + checkInWindow() + } + } + + function stop(event) { // 松开鼠标处理函数 + event = e(event) + // 释放所有操作对象 + document.documentElement.style.overflow = 'auto' // 解除页面滚动限制 + currentObj = document.ontouchmove = document.ontouchend = document.onmousemove = document.onmouseup = null + } + + /** + * 鼠标是否在可拖拽区域内 + * @param {*} event + * @returns + */ + function inDragBox(event, drag) { + const { clientX, clientY } = event // 鼠标位置 + const { offsetHeight, offsetWidth, offsetTop, offsetLeft } = drag.firstElementChild // 窗口位置 + const horizontal = clientX > offsetLeft && clientX < offsetLeft + offsetWidth + const vertical = clientY > offsetTop && clientY < offsetTop + offsetHeight + + if (horizontal && vertical) { + return true + } + + return false + } + + /** + * 若超出窗口则吸附。 + */ + function checkInWindow() { + // 检查是否悬浮在窗口内 + for (const drag of draggableElements) { + // 判断鼠标点击的区域是否是拖拽框内 + const { offsetHeight, offsetWidth, offsetTop, offsetLeft } = drag.firstElementChild + const { clientHeight, clientWidth } = document.documentElement + if (offsetTop < 0) { + drag.firstElementChild.style.top = 0 + } + if (offsetTop > (clientHeight - offsetHeight)) { + drag.firstElementChild.style.top = clientHeight - offsetHeight + 'px' + } + if (offsetLeft < 0) { + drag.firstElementChild.style.left = 0 + } + if (offsetLeft > (clientWidth - offsetWidth)) { + drag.firstElementChild.style.left = clientWidth - offsetWidth + 'px' + } + } + } + + window.addEventListener('resize', checkInWindow) + + return () => { + return () => { + window.removeEventListener('resize', checkInWindow) + } + } + }, []) + + return
+ {children} +
+} + +Draggable.defaultProps = { left: 0, top: 0 } diff --git a/components/ThemeSwitch.js b/components/ThemeSwitch.js index 12d81812..2a8a76e7 100644 --- a/components/ThemeSwitch.js +++ b/components/ThemeSwitch.js @@ -1,17 +1,22 @@ import { useGlobal } from '@/lib/global' - +import React from 'react' +import { Draggable } from './Draggable' /** * * @returns 主题切换 */ -export function ThemeSwitch () { +export function ThemeSwitch() { const { theme, switchTheme } = useGlobal() - return ( -
-
- - 切换主题:{theme} -
-
+ + return (<> + +
+
+ +
{theme}
+
+
+
+ ) } diff --git a/package.json b/package.json index 6bc7ee1b..c4eb488b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "notion-next", - "version": "3.3.4", + "version": "3.3.5", "homepage": "https://github.com/tangly1024/NotionNext.git", "license": "MIT", "repository": { diff --git a/themes/example/LayoutBase.js b/themes/example/LayoutBase.js index 1f357ad8..c99582f4 100644 --- a/themes/example/LayoutBase.js +++ b/themes/example/LayoutBase.js @@ -15,7 +15,7 @@ import JumpToTopButton from './components/JumpToTopButton' const LayoutBase = props => { const { children, meta } = props return ( -
+
{/* 顶栏LOGO */}
@@ -24,7 +24,7 @@ const LayoutBase = props => {