<template>
<article class="prose prose-pre:bg-base-300 prose-a:link-hover max-w-none">
<ContentDoc v-slot="{ doc }">
<div class="flex flex-col md:grid grid-cols-4 gap-8">
<div v-if="doc.toc" class="col-span-1 md:border-r no-prose">
<aside class="sticky top-3">
<div class="mb-2 text-xl font-semibold">Table of Contents</div>
<nav>
<TocList :links="doc.body?.toc?.links" :activeId="activeId" />
</nav>
</aside>
</div>
<ContentRenderer :value="doc" class="col-span-3" />
</div>
</ContentDoc>
</article>
</template>
<script lang="ts" setup>
import { onBeforeUnmount, onMounted, ref } from 'vue';
const activeId = ref('basic-syntax');
onMounted(() => {
let timeoutId: number | null = null;
const callback = (entries: IntersectionObserverEntry[]) => {
for (const entry of entries) {
if (entry.isIntersecting) {
if (timeoutId) {
clearTimeout(timeoutId);
}
timeoutId = window.setTimeout(() => {
activeId.value = entry.target.id;
}, 100);
break;
}
}
};
const observer = new IntersectionObserver(callback, {
root: null,
threshold: [0.5, 0.75, 1.0],
});
const elements = document.querySelectorAll('h2, h3');
for (const element of elements) {
observer.observe(element);
}
onBeforeUnmount(() => {
if (timeoutId) {
clearTimeout(timeoutId);
}
for (const element of elements) {
observer.unobserve(element);
}
});
});
</script>