Files
veridian/app/composables/useAutoScroll.ts
T

64 lines
1.7 KiB
TypeScript

import { ref, watch, onUnmounted, type Ref } from 'vue';
export function useAutoScroll(elementRef: Ref<HTMLElement | null>) {
const userIsScrollingUp = ref(false);
const THRESHOLD = 50;
const isAtBottom = () => {
const el = elementRef.value;
if (!el) return false;
const distanceToBottom = el.scrollHeight - el.scrollTop - el.clientHeight;
return distanceToBottom <= THRESHOLD;
};
const scrollToBottom = (behavior: ScrollBehavior = 'auto') => {
const el = elementRef.value;
if (!el) return;
el.scrollTo({
top: el.scrollHeight,
behavior,
});
};
const handleScroll = () => {
const el = elementRef.value;
if (!el) return;
userIsScrollingUp.value = !isAtBottom();
};
let observer: MutationObserver | null = null;
watch(elementRef, (newEl, oldEl) => {
if (oldEl) {
oldEl.removeEventListener('scroll', handleScroll);
observer?.disconnect();
}
if (newEl) {
newEl.addEventListener('scroll', handleScroll, { passive: true });
observer = new MutationObserver(() => {
if (!userIsScrollingUp.value) {
scrollToBottom();
}
});
observer.observe(newEl, {
childList: true,
subtree: true,
characterData: true
});
}
});
onUnmounted(() => {
elementRef.value?.removeEventListener('scroll', handleScroll);
observer?.disconnect();
});
return {
userIsScrollingUp,
scrollToBottom,
};
}