test/node_modules/@vuepress/theme-default/lib/client/components/VPSidebarItems.vue
2024-08-13 09:27:52 +08:00

82 lines
2.1 KiB
Vue

<script setup lang="ts">
import { useSidebarItems } from '@theme/useSidebarItems'
import VPSidebarItem from '@theme/VPSidebarItem.vue'
import { onMounted, watch } from 'vue'
import { useRoute } from 'vuepress/client'
const route = useRoute()
const sidebarItems = useSidebarItems()
onMounted(() => {
watch(
() => route.hash,
(hash) => {
// get the sidebar DOM
const sidebar = document.querySelector('.vp-sidebar')
if (!sidebar) return
// get the active sidebar item DOM, whose href equals to the current route
const activeSidebarItem = document.querySelector(
`.vp-sidebar a.vp-sidebar-item[href="${route.path}${hash}"]`,
)
if (!activeSidebarItem) return
// get the top and height of the sidebar
const { top: sidebarTop, height: sidebarHeight } =
sidebar.getBoundingClientRect()
// get the top and height of the active sidebar item
const { top: activeSidebarItemTop, height: activeSidebarItemHeight } =
activeSidebarItem.getBoundingClientRect()
// when the active sidebar item overflows the top edge of sidebar
if (activeSidebarItemTop < sidebarTop) {
// scroll to the top edge of sidebar
activeSidebarItem.scrollIntoView(true)
}
// when the active sidebar item overflows the bottom edge of sidebar
else if (
activeSidebarItemTop + activeSidebarItemHeight >
sidebarTop + sidebarHeight
) {
// scroll to the bottom edge of sidebar
activeSidebarItem.scrollIntoView(false)
}
},
)
})
</script>
<template>
<ul v-if="sidebarItems.length" class="vp-sidebar-items">
<VPSidebarItem
v-for="item in sidebarItems"
:key="`${item.text}${item.link}`"
:item="item"
/>
</ul>
</template>
<style lang="scss">
@import '../styles/variables';
.vp-sidebar-items {
margin: 0;
padding: 1.5rem 0;
list-style-type: none;
@media (max-width: $MQMobile) {
padding: 1rem 0;
}
ul {
margin: 0;
padding: 0;
list-style-type: none;
}
a {
display: inline-block;
}
}
</style>