UNPKG

@adaptabletools/adaptable

Version:

Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements

77 lines (76 loc) 2.67 kB
import { useCallback, useRef } from 'react'; class SectionSelector { constructor(node) { this.scrollTop = 0; this.childrenHeights = []; this.select = (scrollTop) => { this.refreshFromDOM(); const relativeCurrentHeight = (scrollTop * this.boxHeight) / this.maxScrollTop; let heightSum = 0; for (let i = 0, len = this.childrenHeights.length; i < len; i++) { heightSum += this.childrenHeights[i]; if (heightSum > relativeCurrentHeight) { return i; } } return this.childrenHeights.length - 1; }; this.node = node; this.refreshFromDOM(); } refreshFromDOM() { this.boxHeight = this.node.scrollHeight; this.childrenHeights = Array.prototype.map.call(this.node.children, (child) => child.offsetHeight); this.maxScrollTop = this.boxHeight - this.node.offsetHeight; } getVisibleRange(scrollTop = this.scrollTop) { const top = scrollTop; const height = this.node.offsetHeight; const bottom = scrollTop + this.node.offsetHeight; return { top, bottom, height, }; } } export const useContainerScrollObserver = (callback) => { const containerNodeRef = useRef(null); const sectionSelectorRef = useRef(null); const update = useCallback((scrollTop) => { callback(sectionSelectorRef.current.select(scrollTop)); }, []); const scrollRafRef = useRef(null); const onScroll = useCallback(() => { if (scrollRafRef.current) { cancelAnimationFrame(scrollRafRef.current); scrollRafRef.current = null; } requestAnimationFrame(() => { scrollRafRef.current = null; update(containerNodeRef.current.scrollTop); }); }, []); const setupScroll = useCallback((node) => { if (node) { containerNodeRef.current = node; node.addEventListener('scroll', onScroll, { passive: true }); sectionSelectorRef.current = new SectionSelector(node); } else { containerNodeRef.current?.removeEventListener('scroll', onScroll); sectionSelectorRef.current = null; } }, []); const ref = setupScroll; return { ref, scrollToIndex: useCallback((index) => { const container = containerNodeRef.current; const node = container.childNodes[index]; node.scrollIntoView({ behavior: 'smooth', }); }, []), }; };