45 lines
1.5 KiB
TypeScript
45 lines
1.5 KiB
TypeScript
const SCROLLABLE_OVERFLOW = new Set(['auto', 'scroll', 'overlay']);
|
|
|
|
function canScrollHorizontally(element: HTMLElement, deltaX: number): boolean {
|
|
if (deltaX === 0) return false;
|
|
|
|
const style = window.getComputedStyle(element);
|
|
if (!SCROLLABLE_OVERFLOW.has(style.overflowX)) return false;
|
|
if (element.scrollWidth <= element.clientWidth) return false;
|
|
|
|
const maxScrollLeft = element.scrollWidth - element.clientWidth;
|
|
if (deltaX < 0) return element.scrollLeft > 0;
|
|
return element.scrollLeft < maxScrollLeft - 1;
|
|
}
|
|
|
|
function canScrollVertically(element: HTMLElement, deltaY: number): boolean {
|
|
if (deltaY === 0) return false;
|
|
|
|
const style = window.getComputedStyle(element);
|
|
if (!SCROLLABLE_OVERFLOW.has(style.overflowY)) return false;
|
|
if (element.scrollHeight <= element.clientHeight) return false;
|
|
|
|
const maxScrollTop = element.scrollHeight - element.clientHeight;
|
|
if (deltaY < 0) return element.scrollTop > 0;
|
|
return element.scrollTop < maxScrollTop - 1;
|
|
}
|
|
|
|
export function canWheelScrollInsideTarget(
|
|
target: EventTarget | null,
|
|
deltaX: number,
|
|
deltaY: number
|
|
): boolean {
|
|
let element = target instanceof Element ? target : null;
|
|
|
|
while (element && element !== document.body && element !== document.documentElement) {
|
|
if (
|
|
element instanceof HTMLElement &&
|
|
(canScrollHorizontally(element, deltaX) || canScrollVertically(element, deltaY))
|
|
) {
|
|
return true;
|
|
}
|
|
element = element.parentElement;
|
|
}
|
|
|
|
return false;
|
|
}
|