From b44161cf0a9a38e6abaae6a0a365ddbac1ff3eac Mon Sep 17 00:00:00 2001 From: Rene Haas Date: Sun, 15 Oct 2023 12:02:45 +0200 Subject: [PATCH] improve update strategy and debounce --- local/browser-testing/src/resize.ts | 1 + .../src/observers/sizeObserver.ts | 38 ++----- .../setups/observersSetup/observersSetup.ts | 47 +++++--- .../setups/scrollbarsSetup/scrollbarsSetup.ts | 5 +- .../updateSegments/overflowUpdateSegment.ts | 23 ++-- .../updateSegments/paddingUpdateSegment.ts | 10 +- .../updateSegments/trinsicUpdateSegment.ts | 5 +- .../src/support/dom/dimensions.ts | 15 +++ .../jest-jsdom/support/dom/dimensions.test.ts | 100 ++++++++++++++++++ .../observers/sizeObserver/index.browser.ts | 34 +++++- .../structureSetup/update/index.browser.ts | 43 ++++---- .../setups/structureSetup/update/index.scss | 2 +- 12 files changed, 236 insertions(+), 87 deletions(-) diff --git a/local/browser-testing/src/resize.ts b/local/browser-testing/src/resize.ts index 7332d205..1b0b6152 100644 --- a/local/browser-testing/src/resize.ts +++ b/local/browser-testing/src/resize.ts @@ -114,6 +114,7 @@ export const resize = (element: HTMLElement) => { }); return { + resizeBtn, addResizeListener(listener: ResizeListener) { resizeListeners.push(listener); }, diff --git a/packages/overlayscrollbars/src/observers/sizeObserver.ts b/packages/overlayscrollbars/src/observers/sizeObserver.ts index 3b79b165..6333742b 100644 --- a/packages/overlayscrollbars/src/observers/sizeObserver.ts +++ b/packages/overlayscrollbars/src/observers/sizeObserver.ts @@ -18,6 +18,7 @@ import { scrollElementTo, selfClearTimeout, wnd, + domRectAppeared, } from '~/support'; import { getEnvironment } from '~/environment'; import { @@ -73,12 +74,6 @@ export const createSizeObserver = ( const [updateResizeObserverContentRectCache] = createCache({ _initialValue: false, _alwaysUpdateValues: true, - _equal: (currVal, newVal) => - !( - !currVal || // if no initial value - // if from display: none to display: block - (!domRectHasDimensions(currVal) && domRectHasDimensions(newVal)) - ), }); return () => { @@ -112,10 +107,10 @@ export const createSizeObserver = ( sizeChangedContext.contentRect ); const hasDimensions = domRectHasDimensions(currRContentRect); - const hadDimensions = domRectHasDimensions(prevContentRect); + const appeared = domRectAppeared(currRContentRect, prevContentRect); const firstCall = !prevContentRect; - appear = !firstCall && !hadDimensions && hasDimensions; - skip = !appear && ((firstCall && !!hadDimensions) || !hasDimensions || isWindowResize); // skip on initial RO. call (if the element visible) or if display is none or when window resize + appear = firstCall || appeared; + skip = !appear && (!hasDimensions || isWindowResize); // skip if display is none or when window resize doDirectionScroll = !skip; // direction scroll when not skipping } @@ -138,16 +133,14 @@ export const createSizeObserver = ( if (!skip) { onSizeChangedCallback({ - _sizeChanged: !hasDirectionCache, _directionIsRTLCache: hasDirectionCache ? sizeChangedContext : undefined, + _sizeChanged: !hasDirectionCache, _appear: appear, }); } isWindowResize = false; }; - let appearCallback: typeof onSizeChangedCallbackProxy | undefined | false = - observeAppearChange && onSizeChangedCallbackProxy; if (ResizeObserverConstructor) { const resizeObserverInstance = new ResizeObserverConstructor((entries) => @@ -158,13 +151,16 @@ export const createSizeObserver = ( resizeObserverInstance.disconnect(); }); } else if (sizeObserverPlugin) { - const [pluginAppearCallback, pluginOffListeners] = sizeObserverPlugin( + const [pluginAppearCallback, pluginDestroyFns] = sizeObserverPlugin( listenerElement, onSizeChangedCallbackProxy, observeAppearChange ); - appearCallback = pluginAppearCallback; - push(destroyFns, pluginOffListeners); + push(destroyFns, [ + pluginDestroyFns, + addClass(sizeObserver, classNameSizeObserverAppear), + addEventListener(sizeObserver, 'animationstart', pluginAppearCallback), + ]); } else { return noop; } @@ -199,18 +195,6 @@ export const createSizeObserver = ( ); } - // appearCallback is always needed on scroll-observer strategy to reset it - if (appearCallback) { - addClass(sizeObserver, classNameSizeObserverAppear); - push( - destroyFns, - addEventListener(sizeObserver, 'animationstart', bind(appearCallback, true), { - // Fire only once for "CSS is ready" event if ResizeObserver strategy is used - _once: !!ResizeObserverConstructor, - }) - ); - } - return bind(runEachAndClear, push(destroyFns, appendChildren(target, sizeObserver))); }; }; diff --git a/packages/overlayscrollbars/src/setups/observersSetup/observersSetup.ts b/packages/overlayscrollbars/src/setups/observersSetup/observersSetup.ts index 7736fe1c..da99530e 100644 --- a/packages/overlayscrollbars/src/setups/observersSetup/observersSetup.ts +++ b/packages/overlayscrollbars/src/setups/observersSetup/observersSetup.ts @@ -6,7 +6,6 @@ import { createCache, debounce, getDirectionIsRTL, - domRectHasDimensions, each, equalWH, fractionalSize, @@ -21,6 +20,7 @@ import { getElmentScroll, scrollElementTo, inArray, + domRectAppeared, } from '~/support'; import { createDOMObserver, createSizeObserver, createTrinsicObserver } from '~/observers'; import { getEnvironment } from '~/environment'; @@ -71,6 +71,9 @@ export const createObserversSetup = ( let debounceMaxDelay: number | false | undefined; let updateContentMutationObserver: (() => void) | undefined; let destroyContentMutationObserver: (() => void) | undefined; + let prevContentRect: DOMRectReadOnly | undefined; + + const { _nativeScrollbarsHiding } = getEnvironment(); const hostSelector = `[${dataAttributeHost}]`; @@ -186,12 +189,24 @@ export const createObserversSetup = ( _directionIsRTLCache, _appear, }: SizeObserverCallbackParams) => { - const updateFn = !_sizeChanged || _appear ? onObserversUpdated : onObserversUpdatedDebounced; + const exclusiveSizeChange = _sizeChanged && !_appear && !_directionIsRTLCache; + const updateFn = + // use debounceed update: + // if native scrollbars hiding is supported + // and if the update is more than just a exclusive sizeChange (e.g. size change + appear, or size change + direction) + !exclusiveSizeChange && _nativeScrollbarsHiding + ? onObserversUpdatedDebounced + : onObserversUpdated; + const [directionIsRTL, directionIsRTLChanged] = _directionIsRTLCache || []; _directionIsRTLCache && assignDeep(state, { _directionIsRTL: directionIsRTL }); - updateFn({ _sizeChanged, _appear, _directionChanged: directionIsRTLChanged }); + updateFn({ + _sizeChanged: _sizeChanged || _appear, + _appear, + _directionChanged: directionIsRTLChanged, + }); }; const onContentMutation = ( @@ -202,6 +217,7 @@ export const createObserversSetup = ( const updateHints = { _contentMutation: contentSizeChanged, }; + // if contentChangedThroughEvent is true its already debounced const updateFn = contentChangedThroughEvent ? onObserversUpdated : onObserversUpdatedDebounced; @@ -247,18 +263,16 @@ export const createObserversSetup = ( } ); - let prevContentRect: DOMRectReadOnly | undefined; const viewportIsTargetResizeObserver = _viewportIsTarget && ResizeObserverConstructor && new ResizeObserverConstructor((entries) => { - const currRContentRect = entries[entries.length - 1].contentRect; - const hasDimensions = domRectHasDimensions(currRContentRect); - const hadDimensions = domRectHasDimensions(prevContentRect); - const _appear = !hadDimensions && hasDimensions; - - onSizeChanged({ _sizeChanged: true, _appear }); - prevContentRect = currRContentRect; + const currContentRect = entries[entries.length - 1].contentRect; + onSizeChanged({ + _sizeChanged: true, + _appear: domRectAppeared(currContentRect, prevContentRect), + }); + prevContentRect = currContentRect; }); return [ @@ -278,7 +292,7 @@ export const createObserversSetup = ( destroyHostMutationObserver(); }; }, - ({ _checkOption, _takeRecords }) => { + ({ _checkOption, _takeRecords, _force }) => { const updateHints: ObserversSetupUpdateHints = {}; const [ignoreMutation] = _checkOption('update.ignoreMutation'); @@ -286,6 +300,7 @@ export const createObserversSetup = ( const [elementEvents, elementEventsChanged] = _checkOption('update.elementEvents'); const [debounceValue, debounceChanged] = _checkOption('update.debounce'); const contentMutationObserverChanged = elementEventsChanged || attributesChanged; + const takeRecords = _takeRecords || _force; const ignoreMutationFromOptions = (mutation: MutationRecord) => isFunction(ignoreMutation) && ignoreMutation(mutation); @@ -336,7 +351,7 @@ export const createObserversSetup = ( } } - if (_takeRecords) { + if (takeRecords) { const hostUpdateResult = updateHostMutationObserver(); const trinsicUpdateResult = updateTrinsicObserver && updateTrinsicObserver(); const contentUpdateResult = @@ -345,14 +360,14 @@ export const createObserversSetup = ( hostUpdateResult && assignDeep( updateHints, - onHostMutation(hostUpdateResult[0], hostUpdateResult[1], _takeRecords) + onHostMutation(hostUpdateResult[0], hostUpdateResult[1], takeRecords) ); trinsicUpdateResult && - assignDeep(updateHints, onTrinsicChanged(trinsicUpdateResult[0], _takeRecords)); + assignDeep(updateHints, onTrinsicChanged(trinsicUpdateResult[0], takeRecords)); contentUpdateResult && - assignDeep(updateHints, onContentMutation(contentUpdateResult[0], _takeRecords)); + assignDeep(updateHints, onContentMutation(contentUpdateResult[0], takeRecords)); } return updateHints; diff --git a/packages/overlayscrollbars/src/setups/scrollbarsSetup/scrollbarsSetup.ts b/packages/overlayscrollbars/src/setups/scrollbarsSetup/scrollbarsSetup.ts index 3a5b5ee1..234dad6d 100644 --- a/packages/overlayscrollbars/src/setups/scrollbarsSetup/scrollbarsSetup.ts +++ b/packages/overlayscrollbars/src/setups/scrollbarsSetup/scrollbarsSetup.ts @@ -155,8 +155,8 @@ export const createScrollbarsSetup = ( const { _overflowEdgeChanged, _overflowAmountChanged, _overflowStyleChanged } = _structureUpdateHints || {}; const { _directionChanged, _appear } = _observersUpdateHints || {}; - const { _nativeScrollbarsOverlaid } = getEnvironment(); const { _directionIsRTL } = observersSetupState; + const { _nativeScrollbarsOverlaid } = getEnvironment(); const { _overflowAmount, _overflowStyle, _hasOverflow } = structureSetupState; const [showNativeOverlaidScrollbarsOption, showNativeOverlaidScrollbarsChanged] = _checkOption('showNativeOverlaidScrollbars'); @@ -169,7 +169,8 @@ export const createScrollbarsSetup = ( const [clickScroll, clickScrollChanged] = _checkOption('scrollbars.clickScroll'); const trulyAppeared = _appear && !_force; const hasOverflow = _hasOverflow.x || _hasOverflow.y; - const updateScrollbars = _overflowEdgeChanged || _overflowAmountChanged || _directionChanged; + const updateScrollbars = + _overflowEdgeChanged || _overflowAmountChanged || _directionChanged || _force; const updateVisibility = _overflowStyleChanged || visibilityChanged; const showNativeOverlaidScrollbars = showNativeOverlaidScrollbarsOption && diff --git a/packages/overlayscrollbars/src/setups/structureSetup/updateSegments/overflowUpdateSegment.ts b/packages/overlayscrollbars/src/setups/structureSetup/updateSegments/overflowUpdateSegment.ts index a000cc17..7fb56272 100644 --- a/packages/overlayscrollbars/src/setups/structureSetup/updateSegments/overflowUpdateSegment.ts +++ b/packages/overlayscrollbars/src/setups/structureSetup/updateSegments/overflowUpdateSegment.ts @@ -354,6 +354,12 @@ export const createOverflowUpdateSegment: CreateStructureUpdateSegment = ( _hostMutation || showNativeOverlaidScrollbarsChanged || _heightIntrinsicChanged); + const adjustViewportArrange = + _sizeChanged || + _paddingStyleChanged || + _contentMutation || + _directionChanged || + showNativeOverlaidScrollbarsChanged; const overflowXVisible = overflowIsVisible(overflow.x); const overflowYVisible = overflowIsVisible(overflow.y); const overflowVisible = overflowXVisible || overflowYVisible; @@ -378,13 +384,7 @@ export const createOverflowUpdateSegment: CreateStructureUpdateSegment = ( fixFlexboxGlue(preMeasureViewportOverflowState, _heightIntrinsic); } - if ( - _sizeChanged || - _paddingStyleChanged || - _contentMutation || - _directionChanged || - showNativeOverlaidScrollbarsChanged - ) { + if (adjustViewportArrange) { if (overflowVisible) { _viewportAddRemoveClass( dataValueViewportOverflowVisible, @@ -463,8 +463,7 @@ export const createOverflowUpdateSegment: CreateStructureUpdateSegment = ( (overflowXVisible && overflowYVisible && (hasOverflow.x || hasOverflow.y)) || (overflowXVisible && hasOverflow.x && !hasOverflow.y) || (overflowYVisible && hasOverflow.y && !hasOverflow.x); - - if ( + const adjustVuewportStyle = _paddingStyleChanged || _directionChanged || sizeFractionChanged || @@ -473,8 +472,10 @@ export const createOverflowUpdateSegment: CreateStructureUpdateSegment = ( overflowAmountChanged || overflowChanged || showNativeOverlaidScrollbarsChanged || - adjustFlexboxGlue - ) { + adjustFlexboxGlue || + adjustViewportArrange; + + if (adjustVuewportStyle) { const viewportStyle: StyleObject = { [strMarginRight]: 0, [strMarginBottom]: 0, diff --git a/packages/overlayscrollbars/src/setups/structureSetup/updateSegments/paddingUpdateSegment.ts b/packages/overlayscrollbars/src/setups/structureSetup/updateSegments/paddingUpdateSegment.ts index 7f212e44..653834c8 100644 --- a/packages/overlayscrollbars/src/setups/structureSetup/updateSegments/paddingUpdateSegment.ts +++ b/packages/overlayscrollbars/src/setups/structureSetup/updateSegments/paddingUpdateSegment.ts @@ -24,7 +24,7 @@ import type { CreateStructureUpdateSegment } from '../structureSetup'; * @returns */ export const createPaddingUpdateSegment: CreateStructureUpdateSegment = ( - { _host, _padding, _viewport, _viewportIsTarget: _isSingleElm }, + { _host, _padding, _viewport, _viewportIsTarget }, state ) => { const [updatePaddingCache, currentPaddingCache] = createCache( @@ -37,22 +37,22 @@ export const createPaddingUpdateSegment: CreateStructureUpdateSegment = ( return ({ _checkOption, _observersUpdateHints, _observersState, _force }) => { let [padding, paddingChanged] = currentPaddingCache(_force); - const { _nativeScrollbarsHiding: _nativeScrollbarStyling, _flexboxGlue } = getEnvironment(); + const { _nativeScrollbarsHiding, _flexboxGlue } = getEnvironment(); const { _sizeChanged, _contentMutation, _directionChanged } = _observersUpdateHints || {}; const { _directionIsRTL } = _observersState; const [paddingAbsolute, paddingAbsoluteChanged] = _checkOption('paddingAbsolute'); - const contentMutation = !_flexboxGlue && _contentMutation; + const contentMutation = _force || (!_flexboxGlue && _contentMutation); if (_sizeChanged || paddingChanged || contentMutation) { [padding, paddingChanged] = updatePaddingCache(_force); } const paddingStyleChanged = - !_isSingleElm && (paddingAbsoluteChanged || _directionChanged || paddingChanged); + !_viewportIsTarget && (paddingAbsoluteChanged || _directionChanged || paddingChanged); if (paddingStyleChanged) { // if there is no padding element and no scrollbar styling, paddingAbsolute isn't supported - const paddingRelative = !paddingAbsolute || (!_padding && !_nativeScrollbarStyling); + const paddingRelative = !paddingAbsolute || (!_padding && !_nativeScrollbarsHiding); const paddingHorizontal = padding.r + padding.l; const paddingVertical = padding.t + padding.b; diff --git a/packages/overlayscrollbars/src/setups/structureSetup/updateSegments/trinsicUpdateSegment.ts b/packages/overlayscrollbars/src/setups/structureSetup/updateSegments/trinsicUpdateSegment.ts index 6c85b289..a8a5f434 100644 --- a/packages/overlayscrollbars/src/setups/structureSetup/updateSegments/trinsicUpdateSegment.ts +++ b/packages/overlayscrollbars/src/setups/structureSetup/updateSegments/trinsicUpdateSegment.ts @@ -9,11 +9,12 @@ import type { CreateStructureUpdateSegment } from '../structureSetup'; */ export const createTrinsicUpdateSegment: CreateStructureUpdateSegment = ({ _content }) => - ({ _observersUpdateHints, _observersState }) => { + ({ _observersUpdateHints, _observersState, _force }) => { const { _flexboxGlue } = getEnvironment(); const { _heightIntrinsicChanged } = _observersUpdateHints || {}; const { _heightIntrinsic } = _observersState; - const heightIntrinsicChanged = (_content || !_flexboxGlue) && _heightIntrinsicChanged; + const heightIntrinsicChanged = + (_content || !_flexboxGlue) && (_heightIntrinsicChanged || _force); if (heightIntrinsicChanged) { style(_content, { diff --git a/packages/overlayscrollbars/src/support/dom/dimensions.ts b/packages/overlayscrollbars/src/support/dom/dimensions.ts index ef4754c3..1ecbc817 100644 --- a/packages/overlayscrollbars/src/support/dom/dimensions.ts +++ b/packages/overlayscrollbars/src/support/dom/dimensions.ts @@ -87,3 +87,18 @@ export const hasDimensions = (elm: HTMLElement | false | null | undefined): bool */ export const domRectHasDimensions = (rect?: DOMRectReadOnly | false | null) => !!(rect && (rect[strHeight] || rect[strWidth])); + +/** + * Determines whether current DOM Rect has appeared according the the previous dom rect.. + * @param currContentRect The current DOM Rect. + * @param prevContentRect The previous DOM Rect. + * @returns Whether the dom rect appeared. + */ +export const domRectAppeared = ( + currContentRect: DOMRectReadOnly | false | null | undefined, + prevContentRect: DOMRectReadOnly | false | null | undefined +) => { + const rectHasDimensions = domRectHasDimensions(currContentRect); + const rectHadDimensions = domRectHasDimensions(prevContentRect); + return !rectHadDimensions && rectHasDimensions; +}; diff --git a/packages/overlayscrollbars/test/jest-jsdom/support/dom/dimensions.test.ts b/packages/overlayscrollbars/test/jest-jsdom/support/dom/dimensions.test.ts index 215f3fbe..361a930a 100644 --- a/packages/overlayscrollbars/test/jest-jsdom/support/dom/dimensions.test.ts +++ b/packages/overlayscrollbars/test/jest-jsdom/support/dom/dimensions.test.ts @@ -8,6 +8,8 @@ import { fractionalSize, getBoundingClientRect, hasDimensions, + domRectHasDimensions, + domRectAppeared, } from '~/support/dom/dimensions'; describe('dom dimensions', () => { @@ -86,6 +88,104 @@ describe('dom dimensions', () => { expect(getBoundingClientRect(document.body)).toEqual(document.body.getBoundingClientRect()); }); + test('domRectHasDimensions', () => { + expect( + domRectHasDimensions({ + width: 0, + height: 0, + bottom: 1, + left: 1, + right: 1, + top: 1, + x: 1, + y: 1, + toJSON: () => '', + }) + ).toBe(false); + expect( + domRectHasDimensions({ + width: 0, + height: 1, + bottom: 0, + left: 0, + right: 0, + top: 0, + x: 0, + y: 0, + toJSON: () => '', + }) + ).toBe(true); + expect( + domRectHasDimensions({ + width: 1, + height: 0, + bottom: 0, + left: 0, + right: 0, + top: 0, + x: 0, + y: 0, + toJSON: () => '', + }) + ).toBe(true); + }); + + test('domRectAppeared', () => { + expect( + domRectAppeared( + { + width: 1, + height: 1, + bottom: 1, + left: 1, + right: 1, + top: 1, + x: 1, + y: 1, + toJSON: () => '', + }, + { + width: 0, + height: 1, + bottom: 0, + left: 0, + right: 0, + top: 0, + x: 0, + y: 0, + toJSON: () => '', + } + ) + ).toBe(false); + + expect( + domRectAppeared( + { + width: 1, + height: 1, + bottom: 1, + left: 1, + right: 1, + top: 1, + x: 1, + y: 1, + toJSON: () => '', + }, + { + width: 0, + height: 0, + bottom: 0, + left: 0, + right: 0, + top: 0, + x: 0, + y: 0, + toJSON: () => '', + } + ) + ).toBe(true); + }); + describe('hasDimensions', () => { test('DOM element', () => { const result = hasDimensions(document.body); diff --git a/packages/overlayscrollbars/test/playwright/observers/sizeObserver/index.browser.ts b/packages/overlayscrollbars/test/playwright/observers/sizeObserver/index.browser.ts index 3f3965f7..a43ee7d2 100644 --- a/packages/overlayscrollbars/test/playwright/observers/sizeObserver/index.browser.ts +++ b/packages/overlayscrollbars/test/playwright/observers/sizeObserver/index.browser.ts @@ -19,8 +19,9 @@ import type { WH } from '~/support'; if (!window.ResizeObserver) { OverlayScrollbars.plugin(SizeObserverPlugin); } - +let updates = 0; let sizeIterations = 0; +let appearIterations = 0; let directionIterations = 0; const contentBox = (elm: HTMLElement | null): WH => { if (elm) { @@ -52,7 +53,7 @@ const preInitChildren = targetElm?.children.length; const constructSizeObserver = createSizeObserver( targetElm as HTMLElement, - ({ _directionIsRTLCache, _sizeChanged }) => { + ({ _directionIsRTLCache, _sizeChanged, _appear }) => { if (_sizeChanged) { sizeIterations += 1; } @@ -61,9 +62,15 @@ const constructSizeObserver = createSizeObserver( directionIterations += 1; } + if (_appear) { + appearIterations += 1; + } + + updates += 1; + requestAnimationFrame(() => { if (resizesSlot) { - resizesSlot.textContent = (directionIterations + sizeIterations).toString(); + resizesSlot.textContent = `${updates}, (size=${sizeIterations}, dir=${directionIterations}, appear=${appearIterations})`; } }); }, @@ -76,37 +83,45 @@ const iterate = async (select: HTMLSelectElement | null, afterEach?: () => any) interface IterateSelect { currSizeIterations: number; currDirectionIterations: number; + currAppearIterations: number; currOffsetSize: WH; currContentSize: WH; currDir: string; currBoxSizing: string; + currHasDimensions: boolean; } await iterateSelect(select, { beforeEach() { const currSizeIterations = sizeIterations; const currDirectionIterations = directionIterations; + const currAppearIterations = appearIterations; const currOffsetSize = offsetSize(targetElm as HTMLElement); const currContentSize = contentBox(targetElm as HTMLElement); const currDir = style(targetElm as HTMLElement, 'direction'); const currBoxSizing = style(targetElm as HTMLElement, 'boxSizing'); + const currHasDimensions = hasDimensions(targetElm as HTMLElement); return { currSizeIterations, currDirectionIterations, + currAppearIterations, currOffsetSize, currContentSize, currDir, currBoxSizing, + currHasDimensions, }; }, async check({ currSizeIterations, currDirectionIterations, + currAppearIterations, currOffsetSize, currContentSize, currDir, currBoxSizing, + currHasDimensions, }) { const newOffsetSize = offsetSize(targetElm as HTMLElement); const newContentSize = contentBox(targetElm as HTMLElement); @@ -164,7 +179,7 @@ const iterate = async (select: HTMLSelectElement | null, afterEach?: () => any) }); } - if (dimensions && (offsetSizeChanged || contentSizeChanged)) { + if (currHasDimensions && dimensions && (offsetSizeChanged || contentSizeChanged)) { await waitForOrFailTest(() => { should.equal( sizeIterations, @@ -174,6 +189,16 @@ const iterate = async (select: HTMLSelectElement | null, afterEach?: () => any) }); } + if (!currHasDimensions && dimensions) { + await waitForOrFailTest(() => { + should.equal( + appearIterations, + currAppearIterations + 1, + 'Appear change was detected correctly.' + ); + }); + } + if (!dimensions) { await timeout(100); } @@ -256,6 +281,7 @@ const start = async () => { console.log('init size changes:', sizeIterations); should.ok(directionIterations > 0, 'Initial direction observations are fired.'); should.ok(sizeIterations > 0, 'Initial size observations are fired.'); + should.ok(appearIterations > 0, 'Initial appear observations are fired.'); targetElm?.removeAttribute('style'); await iterateDisplay(); diff --git a/packages/overlayscrollbars/test/playwright/setups/structureSetup/update/index.browser.ts b/packages/overlayscrollbars/test/playwright/setups/structureSetup/update/index.browser.ts index 75e6a3dc..3d72e663 100644 --- a/packages/overlayscrollbars/test/playwright/setups/structureSetup/update/index.browser.ts +++ b/packages/overlayscrollbars/test/playwright/setups/structureSetup/update/index.browser.ts @@ -191,6 +191,27 @@ selectCallbackEnv(containerBoxSizingSelect); selectCallbackEnv(containerDirectionSelect); selectCallbackEnv(containerMinMaxSelect); +// initialize resize handles always after OverlayScrollbars was initialized to preserve correct parent elements +const targetResizeInstance = resize(target!); +targetResizeInstance.addResizeListener((width, height) => { + style(comparison, { width, height }); +}); +const targetResizeResizeInstance = resize(targetResize!); +targetResizeResizeInstance.addResizeListener((width, height) => { + style(comparisonResize, { width, height }); +}); + +if (!useContentElement) { + envElms.forEach((elm) => { + addClass(elm, 'intrinsicHack'); + }); +} else { + const elms = contents(comparison); + addClass(comparisonContentElm, 'comparisonContent'); + appendChildren(comparison, comparisonContentElm); + appendChildren(comparisonContentElm, elms); +} + // @ts-ignore const osInstance = // @ts-ignore @@ -200,6 +221,9 @@ const osInstance = paddingAbsolute: initialPaddingAbsolute, }, { + initialized(instance) { + instance.elements().target.append(targetResizeInstance.resizeBtn); + }, updated(instance) { updateCount++; const { paddingAbsolute, overflow } = instance.options(); @@ -900,22 +924,3 @@ const start = async () => { }; startBtn!.addEventListener('click', start); - -// initialize resize handles always after OverlayScrollbars was initialized to preserve correct parent elements -resize(target!).addResizeListener((width, height) => { - style(comparison, { width, height }); -}); -resize(targetResize!).addResizeListener((width, height) => { - style(comparisonResize, { width, height }); -}); - -if (!useContentElement) { - envElms.forEach((elm) => { - addClass(elm, 'intrinsicHack'); - }); -} else { - const elms = contents(comparison); - addClass(comparisonContentElm, 'comparisonContent'); - appendChildren(comparison, comparisonContentElm); - appendChildren(comparisonContentElm, elms); -} diff --git a/packages/overlayscrollbars/test/playwright/setups/structureSetup/update/index.scss b/packages/overlayscrollbars/test/playwright/setups/structureSetup/update/index.scss index ff5b01f6..ef11b6de 100644 --- a/packages/overlayscrollbars/test/playwright/setups/structureSetup/update/index.scss +++ b/packages/overlayscrollbars/test/playwright/setups/structureSetup/update/index.scss @@ -317,7 +317,7 @@ body { // disable native scrollbar styling detection body.nsh { - [data-overlayscrollbars-viewport~='scrollbarHidden'].os-environment { + .os-scrollbar-hidden.os-environment { scrollbar-width: auto !important; } .os-scrollbar-hidden.os-environment::-webkit-scrollbar,