Aohina 5 days ago committed by GitHub
commit 8afd2f758e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -1,11 +1,12 @@
<script lang="ts" setup>
import { useScrollLock } from '@vueuse/core'
import { inBrowser } from 'vitepress'
import { ref, watch } from 'vue'
import { inBrowser, useRoute } from 'vitepress'
import { ref, watch, onMounted, onBeforeUnmount, nextTick } from 'vue'
import { useLayout } from '../composables/layout'
import VPSidebarGroup from './VPSidebarGroup.vue'
const { sidebarGroups, hasSidebar } = useLayout()
const route = useRoute()
const props = defineProps<{
open: boolean
@ -35,6 +36,72 @@ watch(
},
{ deep: true }
)
const userScrolled = ref(false)
const isProgrammaticScrolling = ref(false)
const scrollToActiveItem = async (smooth: boolean = true) => {
// if SSR || (Mobile && Not open)
if (!inBrowser || (window.innerWidth < 960 && !props.open)) return
await nextTick()
const container = navEl.value
const activeItem = container?.querySelector('.VPSidebarItem.is-active')
if (!container || !activeItem) return
// set flags
isProgrammaticScrolling.value = true
userScrolled.value = false
activeItem.scrollIntoView({
behavior: smooth ? 'smooth' : 'instant',
block: 'center',
inline: 'nearest'
})
// reset flag when scroll ends
container.addEventListener('scrollend', () => {
isProgrammaticScrolling.value = false
}, { once: true })
}
const onSidebarScroll = () => {
// ignore programmatic scrolls
if (!isProgrammaticScrolling.value) userScrolled.value = true
}
const onWindowResize = () => {
// scroll only if the user has not scrolled manually
if (!userScrolled.value) scrollToActiveItem(false)
}
// route changes
watch(() => route.path, () => scrollToActiveItem(true))
// sidebar content changes
watch(sidebarGroups, () => scrollToActiveItem(false), { deep: true })
// Mobile: when opened
watch(() => props.open, (newOpen) => {
if (newOpen) scrollToActiveItem(false)
})
// scroll once; attach event listeners
onMounted(() => {
scrollToActiveItem(false)
if (inBrowser && navEl.value) {
navEl.value.addEventListener('scroll', onSidebarScroll)
window.addEventListener('resize', onWindowResize)
}
})
// clean up event listeners
onBeforeUnmount(() => {
if (inBrowser && navEl.value) {
navEl.value.removeEventListener('scroll', onSidebarScroll)
window.removeEventListener('resize', onWindowResize)
}
})
</script>
<template>

Loading…
Cancel
Save