2022-05-05 18:13:06 -05:00
|
|
|
<template>
|
|
|
|
<div class="w-screen h-screen max-w-full max-h-screen text-white bg-gradient overflow-hidden">
|
2023-02-05 09:57:57 +05:30
|
|
|
<div id="sidebar" class="hidden md:block overflow-y-auto fixed top-0 left-0 h-full bg-primary border-r border-white border-opacity-25">
|
2022-05-05 18:13:06 -05:00
|
|
|
<div class="flex justify-center items-center py-4 mb-6">
|
|
|
|
<nuxt-link to="/" class="h-12 w-12 -ml-4">
|
|
|
|
<img src="/Logo48.png" class="h-full w-full" />
|
|
|
|
</nuxt-link>
|
|
|
|
<nuxt-link to="/" class="text-2xl pl-2 sm:pl-4 font-book hover:underline">audiobookshelf</nuxt-link>
|
|
|
|
</div>
|
|
|
|
|
2022-12-24 11:04:20 -06:00
|
|
|
<template v-for="category in pageGrouping">
|
|
|
|
<div :key="category.title">
|
|
|
|
<p v-if="category.title !== 'Introduction'" class="px-4 py-1 text-xs font-bold text-white uppercase mt-6 mb-1">{{ category.title }}</p>
|
2022-05-05 18:13:06 -05:00
|
|
|
|
2024-01-05 13:52:01 -07:00
|
|
|
<sidebar-nav-item v-for="item in category.pages"
|
|
|
|
:key="item.hash"
|
|
|
|
:subpath="$route.path"
|
|
|
|
:hash="item.hash"
|
|
|
|
:text="item.title"
|
|
|
|
:selected="currentHash === item.hash"
|
|
|
|
/>
|
2022-12-24 11:04:20 -06:00
|
|
|
</div>
|
|
|
|
</template>
|
2022-05-05 18:13:06 -05:00
|
|
|
</div>
|
|
|
|
<div id="docs-content" class="overflow-y-auto max-w-full overflow-x-hidden">
|
|
|
|
<Nuxt />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
|
|
export default {
|
2022-12-24 11:04:20 -06:00
|
|
|
async fetch() {
|
2023-09-09 16:52:18 -05:00
|
|
|
this.content = await this.$content(this.$route.name, { deep: true }).fetch()
|
2023-02-28 17:15:43 -06:00
|
|
|
this.content.sort((a, b) => Number(a.order) - Number(b.order))
|
2022-12-24 11:04:20 -06:00
|
|
|
|
|
|
|
if (process.env.NODE_ENV === 'development') console.log('CONTENT', this.content)
|
|
|
|
},
|
2022-05-05 18:13:06 -05:00
|
|
|
data() {
|
|
|
|
return {
|
2022-12-24 11:04:20 -06:00
|
|
|
content: [],
|
2022-05-05 18:29:24 -05:00
|
|
|
currentHash: null
|
2022-05-05 18:13:06 -05:00
|
|
|
}
|
|
|
|
},
|
2022-12-24 11:04:20 -06:00
|
|
|
computed: {
|
|
|
|
pageGrouping() {
|
|
|
|
const group = {}
|
|
|
|
this.content.forEach((c) => {
|
|
|
|
if (!group[c.category]) {
|
|
|
|
group[c.category] = {
|
|
|
|
title: c.category,
|
|
|
|
pages: [c]
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
group[c.category].pages.push(c)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
return group
|
|
|
|
}
|
|
|
|
},
|
2022-05-05 18:13:06 -05:00
|
|
|
watch: {
|
|
|
|
'$route.hash'(newVal) {
|
|
|
|
if (newVal) {
|
|
|
|
this.scrollTo(newVal)
|
|
|
|
this.currentHash = newVal
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
scrollTo(hashtag) {
|
2024-01-05 13:52:01 -07:00
|
|
|
const element = document.querySelector(hashtag);
|
|
|
|
if (element) {
|
|
|
|
element.scrollIntoView();
|
|
|
|
}
|
2022-05-05 18:13:06 -05:00
|
|
|
},
|
|
|
|
onScroll(evt) {
|
2022-12-24 11:04:20 -06:00
|
|
|
const clientHeight = evt.target.clientHeight
|
|
|
|
const scrollTop = evt.target.scrollTop
|
|
|
|
const scrollHeight = evt.target.scrollHeight
|
|
|
|
|
|
|
|
// Bottom of page
|
|
|
|
const bottomY = scrollHeight - scrollTop - clientHeight
|
|
|
|
if (bottomY < 200) {
|
|
|
|
const lastItem = this.content[this.content.length - 1]
|
|
|
|
if (lastItem.hash !== this.currentHash) {
|
|
|
|
this.currentHash = lastItem.hash
|
|
|
|
}
|
2022-05-05 18:13:06 -05:00
|
|
|
|
2022-12-24 11:04:20 -06:00
|
|
|
return
|
|
|
|
}
|
2022-05-05 18:13:06 -05:00
|
|
|
|
2022-12-24 11:04:20 -06:00
|
|
|
let closestItem = null
|
|
|
|
for (let i = 0; i < this.content.length; i++) {
|
|
|
|
const item = this.content[i]
|
|
|
|
const div = document.querySelector(item.hash)
|
|
|
|
if (!div) {
|
|
|
|
console.error('Item not found', item)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
const box = div.getBoundingClientRect()
|
2024-01-05 13:52:01 -07:00
|
|
|
if (box.top >= 0 && box.top < window.innerHeight) {
|
2022-05-05 18:13:06 -05:00
|
|
|
closestItem = item
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (closestItem && closestItem.hash !== this.currentHash) {
|
|
|
|
this.currentHash = closestItem.hash
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
mounted() {
|
|
|
|
window['docs-content'].addEventListener('scroll', this.onScroll)
|
2023-09-09 16:52:18 -05:00
|
|
|
setTimeout(() => {
|
|
|
|
if (this.$route.hash) {
|
|
|
|
this.scrollTo(this.$route.hash)
|
|
|
|
this.currentHash = this.$route.hash
|
|
|
|
} else {
|
|
|
|
this.currentHash = '#intro'
|
|
|
|
}
|
|
|
|
}, 100)
|
2022-05-05 18:13:06 -05:00
|
|
|
},
|
|
|
|
beforeDestroy() {
|
|
|
|
window['docs-content'].removeEventListener('scroll', this.onScroll)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style>
|
|
|
|
:root {
|
|
|
|
--sidebar-width: 280px;
|
|
|
|
}
|
|
|
|
|
|
|
|
#sidebar {
|
|
|
|
width: var(--sidebar-width);
|
|
|
|
}
|
|
|
|
#docs-content {
|
|
|
|
margin-left: var(--sidebar-width);
|
|
|
|
height: 100vh;
|
|
|
|
}
|
|
|
|
@media (max-width: 767px) {
|
|
|
|
#docs-content {
|
|
|
|
margin-left: 0px;
|
|
|
|
height: 100vh;
|
|
|
|
}
|
|
|
|
}
|
2023-02-05 09:57:57 +05:30
|
|
|
</style>
|