12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- import { isClient } from '@vueuse/core';
- import { getStyle } from './style';
- export const isScroll = (el: HTMLElement, isVertical?: boolean): boolean => {
- if (!isClient) return false;
- const key = (
- {
- undefined: 'overflow',
- true: 'overflow-y',
- false: 'overflow-x',
- } as const
- )[String(isVertical)]!;
- const overflow = getStyle(el, key);
- return ['scroll', 'auto', 'overlay'].some((s) => overflow.includes(s));
- };
- export const getScrollContainer = (
- el: HTMLElement,
- isVertical?: boolean,
- ): Window | HTMLElement | undefined => {
- if (!isClient) return;
- let parent: HTMLElement = el;
- while (parent) {
- if ([window, document, document.documentElement].includes(parent)) return window;
- if (isScroll(parent, isVertical)) return parent;
- parent = parent.parentNode as HTMLElement;
- }
- return parent;
- };
- let scrollBarWidth: number;
- export const getScrollBarWidth = (namespace: string): number => {
- if (!isClient) return 0;
- if (scrollBarWidth !== undefined) return scrollBarWidth;
- const outer = document.createElement('div');
- outer.className = `${namespace}-scrollbar__wrap`;
- outer.style.visibility = 'hidden';
- outer.style.width = '100px';
- outer.style.position = 'absolute';
- outer.style.top = '-9999px';
- document.body.appendChild(outer);
- const widthNoScroll = outer.offsetWidth;
- outer.style.overflow = 'scroll';
- const inner = document.createElement('div');
- inner.style.width = '100%';
- outer.appendChild(inner);
- const widthWithScroll = inner.offsetWidth;
- outer.parentNode?.removeChild(outer);
- scrollBarWidth = widthNoScroll - widthWithScroll;
- return scrollBarWidth;
- };
- /**
- * Scroll with in the container element, positioning the **selected** element at the top
- * of the container
- */
- export function scrollIntoView(container: HTMLElement, selected: HTMLElement): void {
- if (!isClient) return;
- if (!selected) {
- container.scrollTop = 0;
- return;
- }
- const offsetParents: HTMLElement[] = [];
- let pointer = selected.offsetParent;
- while (pointer !== null && container !== pointer && container.contains(pointer)) {
- offsetParents.push(pointer as HTMLElement);
- pointer = (pointer as HTMLElement).offsetParent;
- }
- const top = selected.offsetTop + offsetParents.reduce((prev, curr) => prev + curr.offsetTop, 0);
- const bottom = top + selected.offsetHeight;
- const viewRectTop = container.scrollTop;
- const viewRectBottom = viewRectTop + container.clientHeight;
- if (top < viewRectTop) {
- container.scrollTop = top;
- } else if (bottom > viewRectBottom) {
- container.scrollTop = bottom - container.clientHeight;
- }
- }
|