import { shallowRef, unref } from 'vue' interface UseScrollToOptions { el: any to: number duration?: number callback?: () => any } function easeInOutQuad(t: number, b: number, c: number, d: number) { t /= d / 2 if (t < 1) return (c / 2) * t * t + b t-- return (-c / 2) * (t * (t - 2) - 1) + b } function move(el: HTMLElement, amount: number) { el.scrollTop = amount } function position(el: HTMLElement) { return el.scrollTop } function useScrollTo({ el, to, duration = 500, callback }: UseScrollToOptions) { const isActiveRef = shallowRef(false) const start = position(el) const change = to - start const increment = 20 let currentTime = 0 const animateScroll = function () { if (!unref(isActiveRef)) return currentTime += increment const val = easeInOutQuad(currentTime, start, change, duration) move(el, val) if (currentTime < duration && unref(isActiveRef)) { requestAnimationFrame(animateScroll) } else { if (callback && typeof callback === 'function') callback() } } const run = () => { isActiveRef.value = true animateScroll() } const stop = () => { isActiveRef.value = false } return { start: run, stop } } export { useScrollTo, type UseScrollToOptions }