UNPKG

@wix/design-system

Version:

@wix/design-system

76 lines 3.63 kB
import { addResizeObserver } from '../../utils/addResizeObserver'; import throttle from 'lodash/throttle'; const addResizeObserverThrottled = (element, cb) => addResizeObserver(element, throttle(cb, 100)); export class FloatingScrollBarState { constructor(params) { this.setFloatingPosition = params.setFloatingPosition; this.setScrollContentSize = params.setScrollContentSize; this.setScrollContentPosition = params.setScrollContentPosition; this.viewportRef = params.viewportRef; this.scrollableContentRef = params.scrollableContentRef; this.scrollElementRef = params.scrollElementRef; } init() { const { setFloatingPosition, setScrollContentSize, setScrollContentPosition, viewportRef, scrollableContentRef, scrollElementRef, } = this; const scrollElement = scrollElementRef?.current; const viewportElement = viewportRef?.current; const scrollableContentElement = scrollableContentRef?.current; const scrollableContentParentElement = scrollableContentElement?.parentElement; if (!viewportElement || !scrollableContentElement || !scrollableContentParentElement || !scrollElement) { return; } const checkIfTableEndExceedsContainer = () => { const scrollableContentRect = scrollableContentElement.getBoundingClientRect(); const scrollElementRect = scrollElement.getBoundingClientRect(); const viewportRect = viewportElement.getBoundingClientRect(); // min between the bottom of viewport element and the bottom of the viewport const viewportVerticalEndRelative = Math.min(scrollElement.clientHeight, viewportElement.clientHeight, window.innerHeight - viewportRect.top); setFloatingPosition(scrollableContentRect.bottom > scrollElementRect.bottom ? { top: viewportVerticalEndRelative, } : undefined); }; const syncPosition = () => { const viewportRect = viewportElement.getBoundingClientRect(); const scrollableContentParentRect = scrollableContentParentElement.getBoundingClientRect(); setScrollContentPosition({ left: scrollableContentParentRect.left - viewportRect.left, width: scrollableContentParentElement.clientWidth, }); }; const syncSize = () => { setScrollContentSize({ width: scrollableContentParentElement.scrollWidth, }); }; const onScroll = throttle(() => { checkIfTableEndExceedsContainer(); }, 100); scrollElement?.addEventListener('scroll', onScroll); const disposers = [ addResizeObserverThrottled(viewportElement, () => { checkIfTableEndExceedsContainer(); syncPosition(); }), addResizeObserverThrottled(scrollableContentElement, () => { checkIfTableEndExceedsContainer(); }), addResizeObserverThrottled(scrollElement, () => { checkIfTableEndExceedsContainer(); }), addResizeObserverThrottled(scrollableContentParentElement, () => { syncSize(); syncPosition(); }), ]; return () => { disposers.forEach(disposer => disposer && disposer()); scrollElement?.removeEventListener('scroll', onScroll); }; } } //# sourceMappingURL=FloatingScrollBarState.js.map