hirsun-vuepress-theme-hope-plus
Version:
A light vuepress theme with tons of features and typewriter effect
193 lines • 7.75 kB
JavaScript
import { usePageData, usePageFrontmatter } from "@vuepress/client";
import { useEventListener, useScrollLock, useThrottleFn, useToggle, } from "@vueuse/core";
import { Transition, computed, defineComponent, h, onMounted, onUnmounted, ref, resolveComponent, watch, } from "vue";
import { useRouter } from "vue-router";
import { RenderDefault, hasGlobalComponent } from "vuepress-shared/client";
import PageFooter from "@theme-hope/components/PageFooter";
import { useThemeLocaleData, useWindowSize, } from "@theme-hope/composables/index";
import Navbar from "@theme-hope/modules/navbar/components/Navbar";
import Sidebar from "@theme-hope/modules/sidebar/components/Sidebar";
import { useSidebarItems } from "@theme-hope/modules/sidebar/composables/index";
import "../styles/common.scss";
export default defineComponent({
name: "CommonWrapper",
props: {
/**
* Extra class of container
*
* 容器额外类名
*/
containerClass: { type: String, default: "" },
/**
* Whether disable navbar
*
* 是否禁用导航栏
*/
noNavbar: Boolean,
/**
* Whether disable sidebar
*
* 是否禁用侧边栏
*/
noSidebar: Boolean,
/**
* Whether disable toc
*/
noToc: Boolean,
},
slots: Object,
setup(props, { slots }) {
const router = useRouter();
const page = usePageData();
const frontmatter = usePageFrontmatter();
const themeLocale = useThemeLocaleData();
const { isMobile, isPC } = useWindowSize();
const [isMobileSidebarOpen, toggleMobileSidebar] = useToggle(false);
const [isDesktopSidebarCollapsed, toggleDesktopSidebar] = useToggle(false);
const sidebarItems = useSidebarItems();
// navbar
const hideNavbar = ref(false);
const enableNavbar = computed(() => {
if (props.noNavbar)
return false;
if (frontmatter.value.navbar === false ||
themeLocale.value.navbar === false)
return false;
return Boolean(page.value.title ||
themeLocale.value.logo ||
themeLocale.value.repo ||
themeLocale.value.navbar);
});
const enableSidebar = computed(() => {
if (props.noSidebar)
return false;
return (frontmatter.value.sidebar !== false &&
sidebarItems.value.length !== 0 &&
!frontmatter.value.home);
});
const enableToc = computed(() => props.noToc || frontmatter.value.home
? false
: frontmatter.value.toc ||
(themeLocale.value.toc !== false && frontmatter.value.toc !== false));
const touchStart = { x: 0, y: 0 };
const onTouchStart = (e) => {
touchStart.x = e.changedTouches[0].clientX;
touchStart.y = e.changedTouches[0].clientY;
};
const onTouchEnd = (e) => {
const dx = e.changedTouches[0].clientX - touchStart.x;
const dy = e.changedTouches[0].clientY - touchStart.y;
if (
// horizontal swipe
Math.abs(dx) > Math.abs(dy) * 1.5 &&
Math.abs(dx) > 40)
if (dx > 0 && touchStart.x <= 80)
toggleMobileSidebar(true);
else
toggleMobileSidebar(false);
};
/** Get scroll distance */
const getScrollTop = () => window.pageYOffset ||
document.documentElement.scrollTop ||
document.body.scrollTop ||
0;
// close sidebar after navigation
let lastDistance = 0;
useEventListener("scroll", useThrottleFn(() => {
const distance = getScrollTop();
// at top or scroll up
if (distance <= 58 || distance < lastDistance)
hideNavbar.value = false;
// scroll down > 200px and sidebar is not opened
else if (lastDistance + 200 < distance && !isMobileSidebarOpen.value)
hideNavbar.value = true;
lastDistance = distance;
}, 300, true));
watch(isMobile, (value) => {
if (!value)
toggleMobileSidebar(false);
});
onMounted(() => {
const isLocked = useScrollLock(document.body);
watch(isMobileSidebarOpen, (value) => {
isLocked.value = value;
});
const unregisterRouterHook = router.afterEach(() => {
toggleMobileSidebar(false);
});
onUnmounted(() => {
isLocked.value = false;
unregisterRouterHook();
});
});
return () => h(hasGlobalComponent("GlobalEncrypt")
? resolveComponent("GlobalEncrypt")
: RenderDefault, () => h("div", {
class: [
"theme-container",
// classes
{
"no-navbar": !enableNavbar.value,
"no-sidebar": !enableSidebar.value &&
!(slots.sidebar || slots.sidebarTop || slots.sidebarBottom),
"has-toc": enableToc.value,
"hide-navbar": hideNavbar.value,
"sidebar-collapsed": !isMobile.value &&
!isPC.value &&
isDesktopSidebarCollapsed.value,
"sidebar-open": isMobile.value && isMobileSidebarOpen.value,
},
props.containerClass,
frontmatter.value.containerClass || "",
],
onTouchStart,
onTouchEnd,
}, [
// navbar
enableNavbar.value
? h(Navbar, { onToggleSidebar: () => toggleMobileSidebar() }, {
startBefore: () => slots.navbarStartBefore?.(),
startAfter: () => slots.navbarStartAfter?.(),
centerBefore: () => slots.navbarCenterBefore?.(),
centerAfter: () => slots.navbarCenterAfter?.(),
endBefore: () => slots.navbarEndBefore?.(),
endAfter: () => slots.navbarEndAfter?.(),
screenTop: () => slots.navScreenTop?.(),
screenBottom: () => slots.navScreenBottom?.(),
})
: null,
// sidebar mask
h(Transition, { name: "fade" }, () => isMobileSidebarOpen.value
? h("div", {
class: "vp-sidebar-mask",
onClick: () => toggleMobileSidebar(false),
})
: null),
// toggle sidebar button
h(Transition, { name: "fade" }, () => isMobile.value
? null
: h("div", {
class: "toggle-sidebar-wrapper",
onClick: () => toggleDesktopSidebar(),
}, h("span", {
class: [
"arrow",
isDesktopSidebarCollapsed.value ? "end" : "start",
],
}))),
// sidebar
h(Sidebar, {}, {
...(slots.sidebar
? {
default: () => slots.sidebar(),
}
: {}),
top: () => slots.sidebarTop?.(),
bottom: () => slots.sidebarBottom?.(),
}),
slots.default(),
h(PageFooter),
]));
},
});
//# sourceMappingURL=CommonWrapper.js.map