63 lines
1.6 KiB
TypeScript
63 lines
1.6 KiB
TypeScript
|
/* eslint-disable no-param-reassign */
|
||
|
|
||
|
let cached: number;
|
||
|
|
||
|
export default function getScrollBarSize(fresh?: boolean) {
|
||
|
if (typeof document === 'undefined') {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (fresh || cached === undefined) {
|
||
|
const inner = document.createElement('div');
|
||
|
inner.style.width = '100%';
|
||
|
inner.style.height = '200px';
|
||
|
|
||
|
const outer = document.createElement('div');
|
||
|
const outerStyle = outer.style;
|
||
|
|
||
|
outerStyle.position = 'absolute';
|
||
|
outerStyle.top = '0';
|
||
|
outerStyle.left = '0';
|
||
|
outerStyle.pointerEvents = 'none';
|
||
|
outerStyle.visibility = 'hidden';
|
||
|
outerStyle.width = '200px';
|
||
|
outerStyle.height = '150px';
|
||
|
outerStyle.overflow = 'hidden';
|
||
|
|
||
|
outer.appendChild(inner);
|
||
|
|
||
|
document.body.appendChild(outer);
|
||
|
|
||
|
const widthContained = inner.offsetWidth;
|
||
|
outer.style.overflow = 'scroll';
|
||
|
let widthScroll = inner.offsetWidth;
|
||
|
|
||
|
if (widthContained === widthScroll) {
|
||
|
widthScroll = outer.clientWidth;
|
||
|
}
|
||
|
|
||
|
document.body.removeChild(outer);
|
||
|
|
||
|
cached = widthContained - widthScroll;
|
||
|
}
|
||
|
return cached;
|
||
|
}
|
||
|
|
||
|
function ensureSize(str: string) {
|
||
|
const match = str.match(/^(.*)px$/);
|
||
|
const value = Number(match?.[1]);
|
||
|
return Number.isNaN(value) ? getScrollBarSize() : value;
|
||
|
}
|
||
|
|
||
|
export function getTargetScrollBarSize(target: HTMLElement) {
|
||
|
if (typeof document === 'undefined' || !target || !(target instanceof Element)) {
|
||
|
return { width: 0, height: 0 };
|
||
|
}
|
||
|
|
||
|
const { width, height } = getComputedStyle(target, '::-webkit-scrollbar');
|
||
|
return {
|
||
|
width: ensureSize(width),
|
||
|
height: ensureSize(height),
|
||
|
};
|
||
|
}
|