mirror of
https://github.com/tenrok/OverlayScrollbars.git
synced 2026-06-17 02:50:35 +03:00
improve sizeobserver with passive listeners, fix raf and setT code, move part of enviroment code to plugin
This commit is contained in:
@@ -11,7 +11,6 @@ import {
|
||||
XY,
|
||||
removeAttr,
|
||||
removeElements,
|
||||
windowSize,
|
||||
equalBCRWH,
|
||||
getBoundingClientRect,
|
||||
assignDeep,
|
||||
@@ -30,6 +29,7 @@ import {
|
||||
import { Options, defaultOptions } from 'options';
|
||||
import { PartialOptions } from 'typings';
|
||||
import { InitializationStrategy } from 'initialization';
|
||||
import { getPlugins, ScrollbarsHidingPluginInstance, scrollbarsHidingPluginName } from 'plugins';
|
||||
|
||||
type EnvironmentEventMap = {
|
||||
_: [];
|
||||
@@ -52,18 +52,12 @@ export interface InternalEnvironment {
|
||||
}
|
||||
|
||||
let environmentInstance: InternalEnvironment;
|
||||
const { abs, round } = Math;
|
||||
|
||||
const diffBiggerThanOne = (valOne: number, valTwo: number): boolean => {
|
||||
const absValOne = abs(valOne);
|
||||
const absValTwo = abs(valTwo);
|
||||
return !(absValOne === absValTwo || absValOne + 1 === absValTwo || absValOne - 1 === absValTwo);
|
||||
};
|
||||
|
||||
const getNativeScrollbarSize = (
|
||||
body: HTMLElement,
|
||||
measureElm: HTMLElement,
|
||||
measureElmChild: HTMLElement
|
||||
measureElmChild: HTMLElement,
|
||||
clear?: boolean
|
||||
): XY => {
|
||||
appendChildren(body, measureElm);
|
||||
|
||||
@@ -71,6 +65,8 @@ const getNativeScrollbarSize = (
|
||||
const oSize = offsetSize(measureElm);
|
||||
const fSize = fractionalSize(measureElmChild);
|
||||
|
||||
clear && removeElements(measureElm);
|
||||
|
||||
return {
|
||||
x: oSize.h - cSize.h + fSize.h,
|
||||
y: oSize.w - cSize.w + fSize.w,
|
||||
@@ -137,26 +133,19 @@ const getFlexboxGlue = (parentElm: HTMLElement, childElm: HTMLElement): boolean
|
||||
return supportsMin && supportsMax;
|
||||
};
|
||||
|
||||
const getWindowDPR = (): number => {
|
||||
// eslint-disable-next-line
|
||||
// @ts-ignore
|
||||
const dDPI = window.screen.deviceXDPI || 0;
|
||||
// eslint-disable-next-line
|
||||
// @ts-ignore
|
||||
const sDPI = window.screen.logicalXDPI || 1;
|
||||
return window.devicePixelRatio || dDPI / sDPI;
|
||||
};
|
||||
|
||||
const createEnvironment = (): InternalEnvironment => {
|
||||
const { body } = document;
|
||||
const envDOM = createDOM(`<div class="${classNameEnvironment}"><div></div></div>`);
|
||||
const envElm = envDOM[0] as HTMLElement;
|
||||
const envChildElm = envElm.firstChild as HTMLElement;
|
||||
const [addEvent, , triggerEvent] = createEventListenerHub<EnvironmentEventMap>();
|
||||
const [updateNativeScrollbarSizeCache, getNativeScrollbarSizeCache] = createCache({
|
||||
_initialValue: getNativeScrollbarSize(body, envElm, envChildElm),
|
||||
_equal: equalXY,
|
||||
});
|
||||
const [updateNativeScrollbarSizeCache, getNativeScrollbarSizeCache] = createCache(
|
||||
{
|
||||
_initialValue: getNativeScrollbarSize(body, envElm, envChildElm),
|
||||
_equal: equalXY,
|
||||
},
|
||||
getNativeScrollbarSize.bind(0, body, envElm, envChildElm, true)
|
||||
);
|
||||
const [nativeScrollbarsSize] = getNativeScrollbarSizeCache();
|
||||
const nativeScrollbarsHiding = getNativeScrollbarsHiding(envElm);
|
||||
const nativeScrollbarsOverlaid = {
|
||||
@@ -197,47 +186,14 @@ const createEnvironment = (): InternalEnvironment => {
|
||||
removeElements(envElm);
|
||||
|
||||
if (!nativeScrollbarsHiding && (!nativeScrollbarsOverlaid.x || !nativeScrollbarsOverlaid.y)) {
|
||||
let size = windowSize();
|
||||
let dpr = getWindowDPR();
|
||||
|
||||
let resizeFn: undefined | ReturnType<ScrollbarsHidingPluginInstance['_envWindowZoom']>;
|
||||
window.addEventListener('resize', () => {
|
||||
const sizeNew = windowSize();
|
||||
const deltaSize = {
|
||||
w: sizeNew.w - size.w,
|
||||
h: sizeNew.h - size.h,
|
||||
};
|
||||
const scrollbarsHidingPlugin = getPlugins()[scrollbarsHidingPluginName] as
|
||||
| ScrollbarsHidingPluginInstance
|
||||
| undefined;
|
||||
|
||||
if (deltaSize.w === 0 && deltaSize.h === 0) return;
|
||||
|
||||
const deltaAbsSize = {
|
||||
w: abs(deltaSize.w),
|
||||
h: abs(deltaSize.h),
|
||||
};
|
||||
const deltaAbsRatio = {
|
||||
w: abs(round(sizeNew.w / (size.w / 100.0))),
|
||||
h: abs(round(sizeNew.h / (size.h / 100.0))),
|
||||
};
|
||||
const dprNew = getWindowDPR();
|
||||
const deltaIsBigger = deltaAbsSize.w > 2 && deltaAbsSize.h > 2;
|
||||
const difference = !diffBiggerThanOne(deltaAbsRatio.w, deltaAbsRatio.h);
|
||||
const dprChanged = dprNew !== dpr && dpr > 0;
|
||||
const isZoom = deltaIsBigger && difference && dprChanged;
|
||||
|
||||
if (isZoom) {
|
||||
const [scrollbarSize, scrollbarSizeChanged] = updateNativeScrollbarSizeCache(
|
||||
getNativeScrollbarSize(body, envElm, envChildElm)
|
||||
);
|
||||
|
||||
assignDeep(environmentInstance._nativeScrollbarsSize, scrollbarSize); // keep the object same!
|
||||
removeElements(envElm);
|
||||
|
||||
if (scrollbarSizeChanged) {
|
||||
triggerEvent('_');
|
||||
}
|
||||
}
|
||||
|
||||
size = sizeNew;
|
||||
dpr = dprNew;
|
||||
resizeFn = resizeFn || (scrollbarsHidingPlugin && scrollbarsHidingPlugin._envWindowZoom());
|
||||
resizeFn && resizeFn(env, updateNativeScrollbarSizeCache, triggerEvent.bind(0, '_'));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
prependChildren,
|
||||
removeElements,
|
||||
on,
|
||||
stopAndPrevent,
|
||||
addClass,
|
||||
push,
|
||||
ResizeObserverConstructor,
|
||||
@@ -18,6 +17,7 @@ import {
|
||||
isBoolean,
|
||||
removeClass,
|
||||
isObject,
|
||||
stopPropagation,
|
||||
} from 'support';
|
||||
import { getEnvironment } from 'environment';
|
||||
import {
|
||||
@@ -190,7 +190,7 @@ export const createSizeObserver = (
|
||||
onSizeChangedCallbackProxy(directionIsRTLCacheValues);
|
||||
}
|
||||
|
||||
stopAndPrevent(event);
|
||||
stopPropagation(event);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -12,9 +12,10 @@ const pluginRegistry: Record<string, PluginInstance> = {};
|
||||
|
||||
export const getPlugins = () => assignDeep({}, pluginRegistry);
|
||||
|
||||
export const addPlugin = (addedPlugin: Plugin | Plugin[]) =>
|
||||
export const addPlugin = (addedPlugin: Plugin | Plugin[]) => {
|
||||
each((isArray(addedPlugin) ? addedPlugin : [addedPlugin]) as Plugin[], (plugin) => {
|
||||
each(keys(plugin), (pluginName) => {
|
||||
pluginRegistry[pluginName] = plugin[pluginName];
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
+83
-8
@@ -1,5 +1,17 @@
|
||||
import { keys, attr, WH, style, addClass, removeClass, noop, each } from 'support';
|
||||
import { getEnvironment } from 'environment';
|
||||
import {
|
||||
keys,
|
||||
attr,
|
||||
WH,
|
||||
style,
|
||||
addClass,
|
||||
removeClass,
|
||||
noop,
|
||||
each,
|
||||
assignDeep,
|
||||
windowSize,
|
||||
UpdateCache,
|
||||
XY,
|
||||
} from 'support';
|
||||
import { classNameViewportArrange } from 'classnames';
|
||||
import type { StyleObject } from 'typings';
|
||||
import type { StructureSetupState } from 'setups/structureSetup';
|
||||
@@ -8,6 +20,7 @@ import type {
|
||||
GetViewportOverflowState,
|
||||
HideNativeScrollbars,
|
||||
} from 'setups/structureSetup/updateSegments/overflowUpdateSegment';
|
||||
import type { InternalEnvironment } from 'environment';
|
||||
import type { Plugin } from 'plugins';
|
||||
|
||||
export type ArrangeViewport = (
|
||||
@@ -29,29 +42,51 @@ export type UndoArrangeViewport = (
|
||||
) => UndoViewportArrangeResult;
|
||||
|
||||
export type ScrollbarsHidingPluginInstance = {
|
||||
_createUniqueViewportArrangeElement(): HTMLStyleElement | false;
|
||||
_createUniqueViewportArrangeElement(env: InternalEnvironment): HTMLStyleElement | false;
|
||||
_overflowUpdateSegment(
|
||||
doViewportArrange: boolean,
|
||||
flexboxGlue: boolean,
|
||||
viewport: HTMLElement,
|
||||
viewportArrange: HTMLStyleElement | false | null | undefined,
|
||||
getState: () => StructureSetupState,
|
||||
getViewportOverflowState: GetViewportOverflowState,
|
||||
hideNativeScrollbars: HideNativeScrollbars
|
||||
): [ArrangeViewport, UndoArrangeViewport];
|
||||
_envWindowZoom(): (
|
||||
envInstance: InternalEnvironment,
|
||||
updateNativeScrollbarSizeCache: UpdateCache<XY<number>>,
|
||||
triggerEvent: () => void
|
||||
) => void;
|
||||
};
|
||||
|
||||
let contentArrangeCounter = 0;
|
||||
const { round, abs } = Math;
|
||||
const getWindowDPR = (): number => {
|
||||
// eslint-disable-next-line
|
||||
// @ts-ignore
|
||||
const dDPI = window.screen.deviceXDPI || 0;
|
||||
// eslint-disable-next-line
|
||||
// @ts-ignore
|
||||
const sDPI = window.screen.logicalXDPI || 1;
|
||||
return window.devicePixelRatio || dDPI / sDPI;
|
||||
};
|
||||
|
||||
const diffBiggerThanOne = (valOne: number, valTwo: number): boolean => {
|
||||
const absValOne = abs(valOne);
|
||||
const absValTwo = abs(valTwo);
|
||||
return !(absValOne === absValTwo || absValOne + 1 === absValTwo || absValOne - 1 === absValTwo);
|
||||
};
|
||||
|
||||
export const scrollbarsHidingPluginName = '__osScrollbarsHidingPlugin';
|
||||
|
||||
export const scrollbarsHidingPlugin: Plugin<ScrollbarsHidingPluginInstance> = {
|
||||
[scrollbarsHidingPluginName]: {
|
||||
_createUniqueViewportArrangeElement: () => {
|
||||
_createUniqueViewportArrangeElement: (env: InternalEnvironment) => {
|
||||
const {
|
||||
_nativeScrollbarsHiding: _nativeScrollbarStyling,
|
||||
_nativeScrollbarsOverlaid: _nativeScrollbarIsOverlaid,
|
||||
_cssCustomProperties,
|
||||
} = getEnvironment();
|
||||
} = env;
|
||||
const create =
|
||||
!_cssCustomProperties &&
|
||||
!_nativeScrollbarStyling &&
|
||||
@@ -67,14 +102,13 @@ export const scrollbarsHidingPlugin: Plugin<ScrollbarsHidingPluginInstance> = {
|
||||
},
|
||||
_overflowUpdateSegment: (
|
||||
doViewportArrange,
|
||||
flexboxGlue,
|
||||
viewport,
|
||||
viewportArrange,
|
||||
getState,
|
||||
getViewportOverflowState,
|
||||
hideNativeScrollbars
|
||||
) => {
|
||||
const { _flexboxGlue } = getEnvironment();
|
||||
|
||||
/**
|
||||
* Sets the styles of the viewport arrange element.
|
||||
* @param viewportOverflowState The viewport overflow state according to which the scrollbars shall be hidden.
|
||||
@@ -182,7 +216,7 @@ export const scrollbarsHidingPlugin: Plugin<ScrollbarsHidingPluginInstance> = {
|
||||
|
||||
removeClass(viewport, classNameViewportArrange);
|
||||
|
||||
if (!_flexboxGlue) {
|
||||
if (!flexboxGlue) {
|
||||
finalPaddingStyle.height = '';
|
||||
}
|
||||
|
||||
@@ -207,5 +241,46 @@ export const scrollbarsHidingPlugin: Plugin<ScrollbarsHidingPluginInstance> = {
|
||||
|
||||
return [arrangeViewport, undoViewportArrange];
|
||||
},
|
||||
_envWindowZoom: () => {
|
||||
let size = windowSize();
|
||||
let dpr = getWindowDPR();
|
||||
|
||||
return (envInstance, updateNativeScrollbarSizeCache, triggerEvent) => {
|
||||
const sizeNew = windowSize();
|
||||
const deltaSize = {
|
||||
w: sizeNew.w - size.w,
|
||||
h: sizeNew.h - size.h,
|
||||
};
|
||||
|
||||
if (deltaSize.w === 0 && deltaSize.h === 0) return;
|
||||
|
||||
const deltaAbsSize = {
|
||||
w: abs(deltaSize.w),
|
||||
h: abs(deltaSize.h),
|
||||
};
|
||||
const deltaAbsRatio = {
|
||||
w: abs(round(sizeNew.w / (size.w / 100.0))),
|
||||
h: abs(round(sizeNew.h / (size.h / 100.0))),
|
||||
};
|
||||
const dprNew = getWindowDPR();
|
||||
const deltaIsBigger = deltaAbsSize.w > 2 && deltaAbsSize.h > 2;
|
||||
const difference = !diffBiggerThanOne(deltaAbsRatio.w, deltaAbsRatio.h);
|
||||
const dprChanged = dprNew !== dpr && dpr > 0;
|
||||
const isZoom = deltaIsBigger && difference && dprChanged;
|
||||
|
||||
if (isZoom) {
|
||||
const [scrollbarSize, scrollbarSizeChanged] = updateNativeScrollbarSizeCache();
|
||||
|
||||
assignDeep(envInstance._nativeScrollbarsSize, scrollbarSize); // keep the object same!
|
||||
|
||||
if (scrollbarSizeChanged) {
|
||||
triggerEvent();
|
||||
}
|
||||
}
|
||||
|
||||
size = sizeNew;
|
||||
dpr = dprNew;
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -6,12 +6,12 @@ import {
|
||||
scrollLeft,
|
||||
scrollTop,
|
||||
on,
|
||||
stopAndPrevent,
|
||||
addClass,
|
||||
equalWH,
|
||||
push,
|
||||
cAF,
|
||||
rAF,
|
||||
stopPropagation,
|
||||
} from 'support';
|
||||
import {
|
||||
classNameSizeObserverListenerScroll,
|
||||
@@ -68,7 +68,7 @@ export const sizeObserverPlugin: Plugin<SizeObserverPluginInstance> = {
|
||||
isDirty = !scrollEvent || !equalWH(currSize, cacheSize);
|
||||
|
||||
if (scrollEvent) {
|
||||
stopAndPrevent(scrollEvent);
|
||||
stopPropagation(scrollEvent);
|
||||
|
||||
if (isDirty && !rAFId) {
|
||||
cAF!(rAFId);
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
removeClass,
|
||||
removeElements,
|
||||
runEachAndClear,
|
||||
setT,
|
||||
stopPropagation,
|
||||
} from 'support';
|
||||
import {
|
||||
@@ -143,7 +144,7 @@ export const createScrollbarsSetupElements = (
|
||||
appendChildren(evaluatedScrollbarSlot, horizontalScrollbars[0]._scrollbar);
|
||||
appendChildren(evaluatedScrollbarSlot, verticalScrollbars[0]._scrollbar);
|
||||
|
||||
setTimeout(() => {
|
||||
setT(() => {
|
||||
addRemoveClassHorizontal(classNamesScrollbarTransitionless);
|
||||
addRemoveClassVertical(classNamesScrollbarTransitionless);
|
||||
}, 300);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { rAF, cAF, isFunction, on, runEachAndClear } from 'support';
|
||||
import { rAF, cAF, isFunction, on, runEachAndClear, setT, clearT } from 'support';
|
||||
import { createState, createOptionCheck } from 'setups/setups';
|
||||
import {
|
||||
createScrollbarsSetupElements,
|
||||
@@ -29,15 +29,15 @@ export interface ScrollbarsSetupStaticState {
|
||||
|
||||
const createSelfCancelTimeout = (timeout?: number | (() => number)) => {
|
||||
let id: number;
|
||||
const setT = timeout ? (setTimeout as (...args: any[]) => number) : rAF!;
|
||||
const clearT = timeout ? clearTimeout : cAF!;
|
||||
const setTFn = timeout ? setT : rAF!;
|
||||
const clearTFn = timeout ? clearT : cAF!;
|
||||
return [
|
||||
(callback: () => any) => {
|
||||
clearT(id);
|
||||
clearTFn(id);
|
||||
// @ts-ignore
|
||||
id = setT(callback, isFunction(timeout) ? timeout() : timeout);
|
||||
id = setTFn(callback, isFunction(timeout) ? timeout() : timeout);
|
||||
},
|
||||
() => clearT(id),
|
||||
() => clearTFn(id),
|
||||
] as [timeout: (callback: () => any) => void, clear: () => void];
|
||||
};
|
||||
|
||||
|
||||
@@ -85,7 +85,8 @@ const addDataAttrHost = (elm: HTMLElement, value: string) => {
|
||||
export const createStructureSetupElements = (
|
||||
target: InitializationTarget
|
||||
): StructureSetupElements => {
|
||||
const { _getInitializationStrategy, _nativeScrollbarsHiding } = getEnvironment();
|
||||
const env = getEnvironment();
|
||||
const { _getInitializationStrategy, _nativeScrollbarsHiding } = env;
|
||||
const scrollbarsHidingPlugin = getPlugins()[scrollbarsHidingPluginName] as
|
||||
| ScrollbarsHidingPluginInstance
|
||||
| undefined;
|
||||
@@ -156,7 +157,7 @@ export const createStructureSetupElements = (
|
||||
!viewportIsTarget &&
|
||||
!_nativeScrollbarsHiding &&
|
||||
createUniqueViewportArrangeElement &&
|
||||
createUniqueViewportArrangeElement(),
|
||||
createUniqueViewportArrangeElement(env),
|
||||
_windowElm: wnd,
|
||||
_documentElm: ownerDocument,
|
||||
_htmlElm: parent(bodyElm) as HTMLHtmlElement,
|
||||
|
||||
+1
@@ -308,6 +308,7 @@ export const createOverflowUpdateSegment: CreateStructureUpdateSegment = (
|
||||
const [arrangeViewport, undoViewportArrange] = scrollbarsHidingPlugin
|
||||
? scrollbarsHidingPlugin._overflowUpdateSegment(
|
||||
doViewportArrange,
|
||||
_flexboxGlue,
|
||||
_viewport,
|
||||
_viewportArrange,
|
||||
getState,
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { jsAPI } from 'support/compatibility/vendors';
|
||||
|
||||
export const MutationObserverConstructor = jsAPI<typeof MutationObserver>('MutationObserver');
|
||||
export const IntersectionObserverConstructor = jsAPI<typeof IntersectionObserver>(
|
||||
'IntersectionObserver'
|
||||
);
|
||||
export const IntersectionObserverConstructor =
|
||||
jsAPI<typeof IntersectionObserver>('IntersectionObserver');
|
||||
export const ResizeObserverConstructor = jsAPI<typeof ResizeObserver>('ResizeObserver');
|
||||
export const cAF = jsAPI<typeof cancelAnimationFrame>('cancelAnimationFrame');
|
||||
export const rAF = jsAPI<typeof requestAnimationFrame>('requestAnimationFrame');
|
||||
export const setT = window.setTimeout as (handler: TimerHandler, timeout?: number) => number;
|
||||
export const clearT = window.clearTimeout as (id?: number) => void;
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
import { isNumber, isFunction } from 'support/utils/types';
|
||||
import { from } from 'support/utils/array';
|
||||
import { rAF, cAF } from 'support/compatibility/apis';
|
||||
|
||||
const clearTimeouts = (id: number | undefined) => {
|
||||
id && clearTimeout(id);
|
||||
id && cAF!(id);
|
||||
};
|
||||
import { rAF, cAF, setT, clearT } from 'support/compatibility/apis';
|
||||
|
||||
type DebounceTiming = number | false | null | undefined;
|
||||
|
||||
@@ -44,17 +39,17 @@ export const debounce = <FunctionToDebounce extends (...args: any) => any>(
|
||||
functionToDebounce: FunctionToDebounce,
|
||||
options?: DebounceOptions<FunctionToDebounce>
|
||||
): Debounced<FunctionToDebounce> => {
|
||||
let timeoutId: number | undefined;
|
||||
let maxTimeoutId: number | undefined;
|
||||
let prevArguments: Parameters<FunctionToDebounce> | null | undefined;
|
||||
let latestArguments: Parameters<FunctionToDebounce> | null | undefined;
|
||||
let clear: () => void = noop;
|
||||
const { _timeout, _maxDelay, _mergeParams } = options || {};
|
||||
const setT = setTimeout as (...args: any[]) => number;
|
||||
|
||||
const invokeFunctionToDebounce = function (args: IArguments) {
|
||||
clearTimeouts(timeoutId);
|
||||
clearTimeouts(maxTimeoutId);
|
||||
maxTimeoutId = timeoutId = prevArguments = undefined;
|
||||
clear();
|
||||
clearT(maxTimeoutId);
|
||||
maxTimeoutId = prevArguments = undefined;
|
||||
clear = noop;
|
||||
// eslint-disable-next-line
|
||||
// @ts-ignore
|
||||
functionToDebounce.apply(this, args);
|
||||
@@ -67,7 +62,7 @@ export const debounce = <FunctionToDebounce extends (...args: any) => any>(
|
||||
|
||||
const flush = () => {
|
||||
/* istanbul ignore next */
|
||||
if (timeoutId) {
|
||||
if (clear !== noop) {
|
||||
invokeFunctionToDebounce(mergeParms(latestArguments!) || latestArguments!);
|
||||
}
|
||||
};
|
||||
@@ -82,6 +77,7 @@ export const debounce = <FunctionToDebounce extends (...args: any) => any>(
|
||||
const finalMaxWait = isFunction(_maxDelay) ? _maxDelay() : _maxDelay;
|
||||
const hasMaxWait = isNumber(finalMaxWait) && finalMaxWait >= 0;
|
||||
const setTimeoutFn = finalTimeout > 0 ? setT : rAF!;
|
||||
const clearTimeoutFn = finalTimeout > 0 ? clearT : cAF!;
|
||||
const mergeParamsResult = mergeParms(args);
|
||||
const invokedArgs = mergeParamsResult || args;
|
||||
const boundInvoke = invokeFunctionToDebounce.bind(0, invokedArgs);
|
||||
@@ -90,9 +86,10 @@ export const debounce = <FunctionToDebounce extends (...args: any) => any>(
|
||||
// invokeFunctionToDebounce(prevArguments || args);
|
||||
// }
|
||||
|
||||
clearTimeouts(timeoutId);
|
||||
clear();
|
||||
// @ts-ignore
|
||||
timeoutId = setTimeoutFn(boundInvoke, finalTimeout as number) as number;
|
||||
const timeoutId = setTimeoutFn(boundInvoke, finalTimeout);
|
||||
clear = () => clearTimeoutFn(timeoutId);
|
||||
|
||||
if (hasMaxWait && !maxTimeoutId) {
|
||||
maxTimeoutId = setT(flush, finalMaxWait as number);
|
||||
|
||||
@@ -1,26 +1,15 @@
|
||||
import { noop, debounce } from 'support/utils/function';
|
||||
import { rAF } from 'support/compatibility/apis';
|
||||
import { rAF, setT } from 'support/compatibility/apis';
|
||||
|
||||
jest.mock('support/compatibility/apis', () => {
|
||||
const originalModule = jest.requireActual('support/compatibility/apis');
|
||||
return {
|
||||
...originalModule,
|
||||
rAF: jest.fn().mockImplementation((...args) => originalModule.rAF(...args)),
|
||||
setT: jest.fn().mockImplementation((...args) => originalModule.setT(...args)),
|
||||
};
|
||||
});
|
||||
|
||||
const mockSetTimeout = () => {
|
||||
const original = window.setTimeout;
|
||||
// @ts-ignore
|
||||
const setT = (window.setTimeout = jest.fn((...args) => original(...args)));
|
||||
return [
|
||||
setT,
|
||||
() => {
|
||||
window.setTimeout = original;
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-return-await
|
||||
const timeout = async (timeout = 100) => await new Promise((r) => setTimeout(r, timeout));
|
||||
|
||||
@@ -34,7 +23,6 @@ describe('function', () => {
|
||||
describe('timeout', () => {
|
||||
test('without timeout', () => {
|
||||
let i = 0;
|
||||
const [setT, unmockSetTimeout] = mockSetTimeout();
|
||||
const debouncedFn = debounce(() => {
|
||||
i += 1;
|
||||
});
|
||||
@@ -44,12 +32,10 @@ describe('function', () => {
|
||||
expect(rAF).not.toHaveBeenCalled();
|
||||
expect(setT).not.toHaveBeenCalled();
|
||||
expect(i).toBe(1);
|
||||
unmockSetTimeout();
|
||||
});
|
||||
|
||||
test('with timeout 0', async () => {
|
||||
let i = 0;
|
||||
const [setT, unmockSetTimeout] = mockSetTimeout();
|
||||
const debouncedFn = debounce(
|
||||
() => {
|
||||
i += 1;
|
||||
@@ -67,12 +53,10 @@ describe('function', () => {
|
||||
await timeout();
|
||||
|
||||
expect(i).toBe(1);
|
||||
unmockSetTimeout();
|
||||
});
|
||||
|
||||
test('with timeout > 0', async () => {
|
||||
let i = 0;
|
||||
const [setT, unmockSetTimeout] = mockSetTimeout();
|
||||
const debouncedFn = debounce(
|
||||
() => {
|
||||
i += 1;
|
||||
@@ -89,8 +73,6 @@ describe('function', () => {
|
||||
expect(i).toBe(0);
|
||||
await timeout();
|
||||
expect(i).toBe(1);
|
||||
|
||||
unmockSetTimeout();
|
||||
});
|
||||
|
||||
test('with timeout > 0 and multiple calls', async () => {
|
||||
|
||||
+1
@@ -30,6 +30,7 @@ if (!window.ResizeObserver) {
|
||||
addPlugin(sizeObserverPlugin);
|
||||
}
|
||||
if (!OverlayScrollbars.env().scrollbarsHiding) {
|
||||
console.log('added');
|
||||
addPlugin(scrollbarsHidingPlugin);
|
||||
}
|
||||
|
||||
|
||||
@@ -104,8 +104,6 @@ body {
|
||||
background: blue;
|
||||
border: 1px solid black;
|
||||
padding: 10px;
|
||||
height: 10000px;
|
||||
width: 10000px;
|
||||
}
|
||||
|
||||
.percent {
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export {};
|
||||
Reference in New Issue
Block a user