aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/docs/composables/useScrollspy.ts
diff options
context:
space:
mode:
Diffstat (limited to 'docs/composables/useScrollspy.ts')
-rw-r--r--docs/composables/useScrollspy.ts39
1 files changed, 39 insertions, 0 deletions
diff --git a/docs/composables/useScrollspy.ts b/docs/composables/useScrollspy.ts
new file mode 100644
index 0000000..5962d0d
--- /dev/null
+++ b/docs/composables/useScrollspy.ts
@@ -0,0 +1,39 @@
+import type { Ref } from 'vue'
+
+/**
+ * Scrollspy allows you to watch visible headings in a specific page.
+ * Useful for table of contents live style updates.
+ */
+export const useScrollspy = () => {
+ const observer = ref() as Ref<IntersectionObserver>
+ const visibleHeadings = ref([]) as Ref<string[]>
+ const activeHeadings = ref([]) as Ref<string[]>
+
+ const observerCallback = (entries: IntersectionObserverEntry[]) =>
+ entries.forEach((entry) => {
+ const id = entry.target.id
+
+ if (entry.isIntersecting) { visibleHeadings.value.push(id) } else { visibleHeadings.value = visibleHeadings.value.filter(t => t !== id) }
+ })
+
+ const updateHeadings = (headings: Element[]) =>
+ headings.forEach((heading) => {
+ observer.value.observe(heading)
+ })
+
+ watch(visibleHeadings, (val, oldVal) => {
+ if (val.length === 0) { activeHeadings.value = oldVal } else { activeHeadings.value = val }
+ }, { deep: true })
+
+ // Create intersection observer
+ onBeforeMount(() => (observer.value = new IntersectionObserver(observerCallback)))
+
+ // Destroy it
+ onBeforeUnmount(() => observer.value?.disconnect())
+
+ return {
+ visibleHeadings,
+ activeHeadings,
+ updateHeadings
+ }
+}