|
|
|
@ -1,8 +1,12 @@
|
|
|
|
|
<script lang="ts" setup>
|
|
|
|
|
import { useWindowScroll } from '@vueuse/core'
|
|
|
|
|
import { computed, shallowRef } from 'vue'
|
|
|
|
|
import { onContentUpdated } from 'vitepress'
|
|
|
|
|
import { useData } from '../composables/data'
|
|
|
|
|
import { getHeaders, type MenuItem } from '../composables/outline'
|
|
|
|
|
import { useSidebar } from '../composables/sidebar'
|
|
|
|
|
import VPIconAlignLeft from './icons/VPIconAlignLeft.vue'
|
|
|
|
|
import VPLocalNavOutlineDropdown from './VPLocalNavOutlineDropdown.vue'
|
|
|
|
|
import VPIconAlignLeft from './icons/VPIconAlignLeft.vue'
|
|
|
|
|
|
|
|
|
|
defineProps<{
|
|
|
|
|
open: boolean
|
|
|
|
@ -14,10 +18,32 @@ defineEmits<{
|
|
|
|
|
|
|
|
|
|
const { theme, frontmatter } = useData()
|
|
|
|
|
const { hasSidebar } = useSidebar()
|
|
|
|
|
const { y } = useWindowScroll()
|
|
|
|
|
|
|
|
|
|
const headers = shallowRef<MenuItem[]>([])
|
|
|
|
|
|
|
|
|
|
onContentUpdated(() => {
|
|
|
|
|
headers.value = getHeaders(frontmatter.value.outline ?? theme.value.outline)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const empty = computed(() => {
|
|
|
|
|
return headers.value.length === 0 && !hasSidebar.value
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const classes = computed(() => {
|
|
|
|
|
return {
|
|
|
|
|
VPLocalNav: true,
|
|
|
|
|
fixed: empty.value,
|
|
|
|
|
'reached-top': y.value >= 64
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
<div class="VPLocalNav" v-if="frontmatter.layout !== 'home'">
|
|
|
|
|
<div
|
|
|
|
|
v-if="frontmatter.layout !== 'home' && (!empty || y >= 64)"
|
|
|
|
|
:class="classes"
|
|
|
|
|
>
|
|
|
|
|
<button
|
|
|
|
|
v-if="hasSidebar"
|
|
|
|
|
class="menu"
|
|
|
|
@ -31,7 +57,7 @@ const { hasSidebar } = useSidebar()
|
|
|
|
|
</span>
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
|
|
<VPLocalNavOutlineDropdown />
|
|
|
|
|
<VPLocalNavOutlineDropdown :headers="headers" />
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
@ -45,11 +71,19 @@ const { hasSidebar } = useSidebar()
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
align-items: center;
|
|
|
|
|
border-top: 1px solid var(--vp-c-gutter);
|
|
|
|
|
border-bottom: 1px solid var(--vp-c-gutter);
|
|
|
|
|
padding-top: var(--vp-layout-top-height, 0px);
|
|
|
|
|
width: 100%;
|
|
|
|
|
background-color: var(--vp-local-nav-bg-color);
|
|
|
|
|
transition: border-color 0.5s, background-color 0.5s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.VPLocalNav.fixed {
|
|
|
|
|
position: fixed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.VPLocalNav.reached-top {
|
|
|
|
|
border-top-color: transparent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media (min-width: 960px) {
|
|
|
|
|