import type { Ref } from 'vue'; import type { RafFrame } from '../../_util/raf'; import raf from '../../_util/raf'; import isFF from '../utils/isFirefox'; import useOriginScroll from './useOriginScroll'; interface FireFoxDOMMouseScrollEvent { detail: number; preventDefault: Function; } export default function useFrameWheel( inVirtual: Ref, isScrollAtTop: Ref, isScrollAtBottom: Ref, onWheelDelta: (offset: number) => void, ): [(e: WheelEvent) => void, (e: FireFoxDOMMouseScrollEvent) => void] { let offsetRef = 0; let nextFrame: RafFrame = null; // Firefox patch let wheelValue = null; let isMouseScroll = false; // Scroll status sync const originScroll = useOriginScroll(isScrollAtTop, isScrollAtBottom); function onWheel(event: { preventDefault?: any; deltaY?: any }) { if (!inVirtual.value) return; raf.cancel(nextFrame!); const { deltaY } = event; offsetRef += deltaY; wheelValue = deltaY; // Do nothing when scroll at the edge, Skip check when is in scroll if (originScroll(deltaY)) return; // Proxy of scroll events if (!isFF) { event.preventDefault(); } nextFrame = raf(() => { // Patch a multiple for Firefox to fix wheel number too small // ref: https://github.com/ant-design/ant-design/issues/26372#issuecomment-679460266 const patchMultiple = isMouseScroll ? 10 : 1; onWheelDelta(offsetRef * patchMultiple); offsetRef = 0; }); } // A patch for firefox function onFireFoxScroll(event: { detail: any }) { if (!inVirtual.value) return; isMouseScroll = event.detail === wheelValue; } return [onWheel, onFireFoxScroll]; }