mirror of
https://github.com/tenrok/OverlayScrollbars.git
synced 2026-05-17 07:29:40 +03:00
fix size observer for content-box
This commit is contained in:
@@ -57,7 +57,7 @@ export const createLifecycleBase = <O, C>(
|
||||
const cacheOptions = createCache<O>(options, true);
|
||||
|
||||
const update = (hints: LifecycleUpdateHints<O, C>) => {
|
||||
const hasForce = isBoolean(hints._force);
|
||||
const hasForce = isBoolean(hints._force); // indication that it was called from outside
|
||||
const force = hints._force === true;
|
||||
|
||||
const changedCache = cacheChange(force ? null : hints._changedCache || (hasForce ? null : []), force);
|
||||
|
||||
@@ -29,7 +29,7 @@ export const createStructureLifecycle = (
|
||||
target: OSTargetObject,
|
||||
initialOptions?: StructureLifecycleOptions
|
||||
): Lifecycle<StructureLifecycleOptions> => {
|
||||
const { host, viewport, content } = target;
|
||||
const { host, padding: paddingElm, viewport, content } = target;
|
||||
const destructFns: (() => any)[] = [];
|
||||
const env: Environment = getEnvironment();
|
||||
const scrollbarsOverlaid = env._nativeScrollbarIsOverlaid;
|
||||
@@ -74,7 +74,7 @@ export const createStructureLifecycle = (
|
||||
paddingStyle.b -= env._nativeScrollbarSize.x;
|
||||
}
|
||||
|
||||
style(viewport, { top: paddingStyle.t, left: paddingStyle.l, 'margin-right': paddingStyle.r, 'margin-bottom': paddingStyle.b });
|
||||
style(paddingElm, { top: paddingStyle.t, left: paddingStyle.l, 'margin-right': paddingStyle.r, 'margin-bottom': paddingStyle.b });
|
||||
}
|
||||
|
||||
console.log(options); // eslint-disable-line
|
||||
|
||||
@@ -25,6 +25,7 @@ const ResizeObserverConstructor = jsAPI('ResizeObserver');
|
||||
const classNameSizeObserver = 'os-size-observer';
|
||||
const classNameSizeObserverAppear = `${classNameSizeObserver}-appear`;
|
||||
const classNameSizeObserverListener = `${classNameSizeObserver}-listener`;
|
||||
const classNameSizeObserverListenerScroll = `${classNameSizeObserverListener}-scroll`;
|
||||
const classNameSizeObserverListenerItem = `${classNameSizeObserverListener}-item`;
|
||||
const classNameSizeObserverListenerItemFinal = `${classNameSizeObserverListenerItem}-final`;
|
||||
const cAF = cancelAnimationFrame;
|
||||
@@ -65,6 +66,7 @@ export const createSizeObserver = (
|
||||
`<div class="${classNameSizeObserverListenerItem}" dir="ltr"><div class="${classNameSizeObserverListenerItem}"><div class="${classNameSizeObserverListenerItemFinal}"></div></div><div class="${classNameSizeObserverListenerItem}"><div class="${classNameSizeObserverListenerItemFinal}" style="width: 200%; height: 200%"></div></div></div>`
|
||||
);
|
||||
appendChildren(listenerElement, observerElementChildren);
|
||||
addClass(listenerElement, classNameSizeObserverListenerScroll);
|
||||
const observerElementChildrenRoot = observerElementChildren[0] as HTMLElement;
|
||||
const shrinkElement = observerElementChildrenRoot.lastChild as HTMLElement;
|
||||
const expandElement = observerElementChildrenRoot.firstChild as HTMLElement;
|
||||
|
||||
@@ -6,6 +6,7 @@ import { createTrinsicObserver } from 'observers/trinsicObserver';
|
||||
import { Lifecycle } from 'lifecycles/lifecycleBase';
|
||||
|
||||
const classNameHost = 'os-host';
|
||||
const classNamePadding = 'os-padding';
|
||||
const classNameViewport = 'os-viewport';
|
||||
const classNameContent = 'os-content';
|
||||
|
||||
@@ -13,25 +14,29 @@ const normalizeTarget = (target: OSTarget): OSTargetObject => {
|
||||
if (isHTMLElement(target)) {
|
||||
const isTextarea = is(target, 'textarea');
|
||||
const host = (isTextarea ? createDiv() : target) as HTMLElement;
|
||||
const padding = createDiv(classNamePadding);
|
||||
const viewport = createDiv(classNameViewport);
|
||||
const content = createDiv(classNameContent);
|
||||
|
||||
appendChildren(padding, viewport);
|
||||
appendChildren(viewport, content);
|
||||
appendChildren(content, contents(target));
|
||||
appendChildren(target, viewport);
|
||||
appendChildren(target, padding);
|
||||
addClass(host, classNameHost);
|
||||
|
||||
return {
|
||||
target,
|
||||
host,
|
||||
padding,
|
||||
viewport,
|
||||
content,
|
||||
};
|
||||
}
|
||||
|
||||
const { host, viewport, content } = target;
|
||||
const { host, padding, viewport, content } = target;
|
||||
|
||||
addClass(host, classNameHost);
|
||||
addClass(padding, classNamePadding);
|
||||
addClass(viewport, classNameViewport);
|
||||
addClass(content, classNameContent);
|
||||
|
||||
|
||||
@@ -34,9 +34,8 @@ $scrollbar-cushion: 100px;
|
||||
|
||||
.os-size-observer-listener {
|
||||
display: block;
|
||||
height: 200%;
|
||||
width: 200%;
|
||||
box-sizing: content-box;
|
||||
height: 500%;
|
||||
width: 500%;
|
||||
|
||||
// lets assume no scrollbar is 100px wide
|
||||
& > .os-size-observer-listener-item {
|
||||
@@ -47,6 +46,10 @@ $scrollbar-cushion: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
.os-size-observer-listener-scroll {
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
.os-size-observer-listener-item {
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
.os-host {
|
||||
.os-host,
|
||||
.os-padding {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.os-padding,
|
||||
.os-viewport {
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
@@ -15,6 +17,8 @@
|
||||
margin: 0;
|
||||
border: none;
|
||||
overflow: visible;
|
||||
max-width: 100%;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.os-content {
|
||||
|
||||
@@ -5,6 +5,7 @@ export type OSTargetElement = HTMLElement | HTMLTextAreaElement;
|
||||
export interface OSTargetObject {
|
||||
target: OSTargetElement;
|
||||
host: HTMLElement;
|
||||
padding: HTMLElement;
|
||||
viewport: HTMLElement;
|
||||
content: HTMLElement;
|
||||
}
|
||||
|
||||
+14
-10
@@ -10,16 +10,16 @@ import { createSizeObserver } from 'observers/sizeObserver';
|
||||
|
||||
let sizeIterations = 0;
|
||||
let directionIterations = 0;
|
||||
const contentBox = (elm: HTMLElement | null) => {
|
||||
const contentBox = (elm: HTMLElement | null): WH<number> => {
|
||||
if (elm) {
|
||||
const computedStyle = window.getComputedStyle(elm);
|
||||
return {
|
||||
width: elm.clientWidth - (parseFloat(computedStyle.paddingLeft) + parseFloat(computedStyle.paddingRight)),
|
||||
height: elm.clientHeight - (parseFloat(computedStyle.paddingTop) + parseFloat(computedStyle.paddingBottom)),
|
||||
w: elm.clientWidth - (parseFloat(computedStyle.paddingLeft) + parseFloat(computedStyle.paddingRight)),
|
||||
h: elm.clientHeight - (parseFloat(computedStyle.paddingTop) + parseFloat(computedStyle.paddingBottom)),
|
||||
};
|
||||
}
|
||||
|
||||
return { width: 0, height: 0 };
|
||||
return { w: 0, h: 0 };
|
||||
};
|
||||
|
||||
const targetElm = document.querySelector('#target');
|
||||
@@ -39,6 +39,7 @@ const iterate = async (select: HTMLSelectElement | null, afterEach?: () => any)
|
||||
currSizeIterations: number;
|
||||
currDirectionIterations: number;
|
||||
currOffsetSize: WH<number>;
|
||||
currContentSize: WH<number>;
|
||||
currDir: string;
|
||||
}
|
||||
|
||||
@@ -47,36 +48,39 @@ const iterate = async (select: HTMLSelectElement | null, afterEach?: () => any)
|
||||
const currSizeIterations = sizeIterations;
|
||||
const currDirectionIterations = directionIterations;
|
||||
const currOffsetSize = offsetSize(targetElm as HTMLElement);
|
||||
const currContentSize = contentBox(targetElm as HTMLElement);
|
||||
const currDir = style(targetElm as HTMLElement, 'direction');
|
||||
|
||||
return {
|
||||
currSizeIterations,
|
||||
currDirectionIterations,
|
||||
currOffsetSize,
|
||||
currContentSize,
|
||||
currDir,
|
||||
};
|
||||
},
|
||||
async check({ currSizeIterations, currDirectionIterations, currOffsetSize, currDir }) {
|
||||
async check({ currSizeIterations, currDirectionIterations, currOffsetSize, currContentSize, currDir }) {
|
||||
const newOffsetSize = offsetSize(targetElm as HTMLElement);
|
||||
const newContentSize = contentBox(targetElm as HTMLElement);
|
||||
const newDir = style(targetElm as HTMLElement, 'direction');
|
||||
const offsetSizeChanged = currOffsetSize.w !== newOffsetSize.w || currOffsetSize.h !== newOffsetSize.h;
|
||||
const contentSizeChanged = currContentSize.w !== newContentSize.w || currContentSize.h !== newContentSize.h;
|
||||
const dirChanged = currDir !== newDir;
|
||||
const dimensions = hasDimensions(targetElm as HTMLElement);
|
||||
const contentSize = contentBox(targetElm as HTMLElement);
|
||||
const observerElm = targetElm?.firstElementChild as HTMLElement;
|
||||
|
||||
// no overflow if not needed
|
||||
if (targetElm && contentSize.width > 0) {
|
||||
if (targetElm && newContentSize.w > 0) {
|
||||
should.ok(observerElm.getBoundingClientRect().right <= targetElm.getBoundingClientRect().right);
|
||||
}
|
||||
if (targetElm && contentSize.height > 0) {
|
||||
if (targetElm && newContentSize.h > 0) {
|
||||
should.ok(observerElm.getBoundingClientRect().bottom <= targetElm.getBoundingClientRect().bottom);
|
||||
}
|
||||
|
||||
if (dimensions && (offsetSizeChanged || dirChanged)) {
|
||||
if (dimensions && (offsetSizeChanged || contentSizeChanged || dirChanged)) {
|
||||
await waitFor(
|
||||
() => {
|
||||
if (offsetSizeChanged) {
|
||||
if (offsetSizeChanged || contentSizeChanged) {
|
||||
should.equal(sizeIterations, currSizeIterations + 1);
|
||||
}
|
||||
if (dirChanged) {
|
||||
|
||||
Reference in New Issue
Block a user