UNPKG

overlayscrollbars

Version:

A javascript scrollbar plugin that hides the native scrollbars, provides custom styleable overlay scrollbars, and preserves the native functionality and feel.

1 lines 370 kB
{"version":3,"file":"overlayscrollbars.mjs","sources":["../src/support/cache.ts","../src/support/compatibility/isBrowser.ts","../src/support/utils/alias.ts","../src/support/compatibility/apis.ts","../src/support/utils/types.ts","../src/support/utils/animation.ts","../src/support/utils/array.ts","../src/support/utils/strings.ts","../src/support/utils/equal.ts","../src/support/utils/function.ts","../src/support/utils/object.ts","../src/support/utils/noop.ts","../src/support/utils/math.ts","../src/support/dom/attribute.ts","../src/support/dom/class.ts","../src/support/dom/traversal.ts","../src/support/dom/manipulation.ts","../src/trustedTypePolicy.ts","../src/support/dom/create.ts","../src/support/dom/style.ts","../src/support/dom/dimensions.ts","../src/support/dom/events.ts","../src/support/dom/scroll.ts","../src/support/dom/focus.ts","../src/support/eventListeners.ts","../src/plugins/plugins.ts","../src/plugins/optionsValidationPlugin/optionsValidationPlugin.ts","../src/classnames.ts","../src/plugins/sizeObserverPlugin/sizeObserverPlugin.ts","../src/setups/structureSetup/structureSetup.utils.ts","../src/plugins/scrollbarsHidingPlugin/scrollbarsHidingPlugin.ts","../src/plugins/clickScrollPlugin/clickScrollPlugin.ts","../src/options.ts","../src/nonce.ts","../src/environment.ts","../src/observers/domObserver.ts","../src/observers/sizeObserver.ts","../src/observers/trinsicObserver.ts","../src/setups/observersSetup/observersSetup.ts","../src/initialization.ts","../src/setups/scrollbarsSetup/scrollbarsSetup.elements.ts","../src/setups/scrollbarsSetup/scrollbarsSetup.events.ts","../src/setups/scrollbarsSetup/scrollbarsSetup.ts","../src/setups/structureSetup/structureSetup.elements.ts","../src/setups/structureSetup/updateSegments/trinsicUpdateSegment.ts","../src/setups/structureSetup/updateSegments/paddingUpdateSegment.ts","../src/setups/structureSetup/updateSegments/overflowUpdateSegment.ts","../src/setups/structureSetup/structureSetup.ts","../src/setups/setups.ts","../src/instances.ts","../src/overlayscrollbars.ts"],"sourcesContent":["export interface CacheOptions<Value> {\n // initial value of _value.\n _initialValue: Value;\n // Custom comparison function if shallow compare isn't enough. Returns true if nothing changed.\n _equal?: EqualCachePropFunction<Value>;\n // If true always updates _value and _previous, otherwise they update only when they changed.\n _alwaysUpdateValues?: boolean;\n}\n\nexport type CacheValues<T> = [value: T, changed: boolean, previous?: T];\n\nexport type EqualCachePropFunction<Value> = (currentVal: Value, newVal: Value) => boolean;\n\nexport type CacheUpdater<Value> = (current: Value, previous?: Value) => Value;\n\nexport type UpdateCacheContextual<Value> = (newValue: Value, force?: boolean) => CacheValues<Value>;\n\nexport type UpdateCache<Value> = (force?: boolean) => CacheValues<Value>;\n\nexport type GetCurrentCache<Value> = (force?: boolean) => CacheValues<Value>;\n\nexport type Cache<Value> = [UpdateCache<Value>, GetCurrentCache<Value>];\n\nexport type CacheContextual<Value> = [UpdateCacheContextual<Value>, GetCurrentCache<Value>];\n\ntype CreateCache = {\n <Value>(options: CacheOptions<Value>): CacheContextual<Value>;\n <Value>(options: CacheOptions<Value>, update: CacheUpdater<Value>): Cache<Value>;\n <Value>(\n options: CacheOptions<Value>,\n update?: CacheUpdater<Value>\n ): CacheContextual<Value> | Cache<Value>;\n};\n\nexport const createCache: CreateCache = <Value>(\n options: CacheOptions<Value>,\n update?: CacheUpdater<Value>\n): CacheContextual<Value> | Cache<Value> => {\n const { _initialValue, _equal, _alwaysUpdateValues } = options;\n let _value: Value = _initialValue;\n let _previous: Value | undefined;\n\n const cacheUpdateContextual: UpdateCacheContextual<Value> = (newValue, force?) => {\n const curr = _value;\n\n const newVal = newValue;\n const changed = force || (_equal ? !_equal(curr, newVal) : curr !== newVal);\n\n if (changed || _alwaysUpdateValues) {\n _value = newVal;\n _previous = curr;\n }\n\n return [_value, changed, _previous];\n };\n const cacheUpdateIsolated: UpdateCache<Value> = (force?) =>\n cacheUpdateContextual(update!(_value, _previous), force);\n\n const getCurrentCache: GetCurrentCache<Value> = (force?: boolean) => [\n _value,\n !!force, // changed\n _previous,\n ];\n\n return [update ? cacheUpdateIsolated : cacheUpdateContextual, getCurrentCache] as\n | CacheContextual<Value>\n | Cache<Value>;\n};\n","export const isBrowser =\n // deno has the global `window` defined\n typeof window !== 'undefined' &&\n // make sure HTML element is available\n typeof HTMLElement !== 'undefined' &&\n // make sure document is defined\n !!window.document;\n","import { isBrowser } from '../compatibility/isBrowser';\n\nexport const wnd = (isBrowser ? window : {}) as typeof window;\nexport const mathMax = Math.max;\nexport const mathMin = Math.min;\nexport const mathRound = Math.round;\nexport const mathFloor = Math.floor;\nexport const mathCeil = Math.ceil;\nexport const mathAbs = Math.abs;\nexport const mathSign = Math.sign;\nexport const cAF = wnd.cancelAnimationFrame;\nexport const rAF = wnd.requestAnimationFrame;\nexport const setT = wnd.setTimeout;\nexport const clearT = wnd.clearTimeout;\n","import { wnd } from '../utils/alias';\n\nconst getApi = <T>(name: string) =>\n (typeof wnd[name as keyof typeof wnd] !== 'undefined'\n ? wnd[name as keyof typeof wnd]\n : undefined) as T;\n\nexport const MutationObserverConstructor = getApi<typeof MutationObserver>('MutationObserver');\nexport const IntersectionObserverConstructor =\n getApi<typeof IntersectionObserver>('IntersectionObserver');\nexport const ResizeObserverConstructor = getApi<typeof ResizeObserver>('ResizeObserver');\nexport const scrollT = getApi<new (constructor: unknown) => AnimationTimeline>('ScrollTimeline');\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type { PlainObject } from '../../typings';\n\nexport const isUndefined = (obj: any): obj is undefined => obj === undefined;\n\nexport const isNull = (obj: any): obj is null => obj === null;\n\nexport const type = (obj: any): string =>\n isUndefined(obj) || isNull(obj)\n ? `${obj}`\n : Object.prototype.toString\n .call(obj)\n .replace(/^\\[object (.+)\\]$/, '$1')\n .toLowerCase();\n\nexport const isNumber = (obj: any): obj is number => typeof obj === 'number';\n\nexport const isString = (obj: any): obj is string => typeof obj === 'string';\n\nexport const isBoolean = (obj: any): obj is boolean => typeof obj === 'boolean';\n\nexport const isFunction = (obj: any): obj is (...args: any[]) => any => typeof obj === 'function';\n\nexport const isArray = <T = any>(obj: any): obj is Array<T> => Array.isArray(obj);\n\nexport const isObject = (obj: any): obj is object =>\n typeof obj === 'object' && !isArray(obj) && !isNull(obj);\n\n/**\n * Returns true if the given object is array like, false otherwise.\n * @param obj The Object\n */\nexport const isArrayLike = <T extends PlainObject = any>(obj: any): obj is ArrayLike<T> => {\n const length = !!obj && obj.length;\n const lengthCorrectFormat = isNumber(length) && length > -1 && length % 1 == 0;\n\n return isArray(obj) || (!isFunction(obj) && lengthCorrectFormat)\n ? length > 0 && isObject(obj)\n ? length - 1 in obj\n : true\n : false;\n};\n\n/**\n * Returns true if the given object is a \"plain\" (e.g. { key: value }) object, false otherwise.\n * @param obj The Object.\n */\nexport const isPlainObject = <T = any>(obj: any): obj is PlainObject<T> =>\n !!obj && obj.constructor === Object;\n\n/**\n * Checks whether the given object is a HTMLElement.\n * @param obj The object which shall be checked.\n */\nexport const isHTMLElement = (obj: any): obj is HTMLElement => obj instanceof HTMLElement;\n\n/**\n * Checks whether the given object is a Element.\n * @param obj The object which shall be checked.\n */\nexport const isElement = (obj: any): obj is Element => obj instanceof Element;\n","import { mathMax, rAF, cAF } from './alias';\nimport { isFunction } from './types';\n\n/**\n * percent: current percent (0 - 1),\n * time: current time (duration * percent),\n * min: start value\n * max: end value\n * duration: duration in ms\n */\nexport type EasingFn = (\n percent: number,\n time: number,\n min: number,\n max: number,\n duration: number\n) => number;\n\nconst animationCurrentTime = () => performance.now();\n\nexport const animateNumber = (\n from: number,\n to: number,\n duration: number,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onFrame: (progress: number, percent: number, completed: boolean) => any,\n easing?: EasingFn | false\n): ((complete?: boolean) => void) => {\n let animationFrameId = 0;\n const timeStart = animationCurrentTime();\n const finalDuration = mathMax(0, duration);\n const frame = (complete?: boolean) => {\n const timeNow = animationCurrentTime();\n const timeElapsed = timeNow - timeStart;\n const stopAnimation = timeElapsed >= finalDuration;\n const percent = complete\n ? 1\n : 1 - (mathMax(0, timeStart + finalDuration - timeNow) / finalDuration || 0);\n const progress =\n (to - from) *\n (isFunction(easing)\n ? easing(percent, percent * finalDuration, 0, 1, finalDuration)\n : percent) +\n from;\n const animationCompleted = stopAnimation || percent === 1;\n\n onFrame(progress, percent, animationCompleted);\n\n animationFrameId = animationCompleted ? 0 : rAF!(() => frame());\n };\n frame();\n return (complete) => {\n cAF!(animationFrameId);\n if (complete) {\n frame(complete);\n }\n };\n};\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type { PlainObject } from '../../typings';\nimport { isArray, isArrayLike, isString } from './types';\n\ntype RunEachItem = ((...args: any) => any | any[]) | false | null | undefined;\n\nexport function each<T extends Array<unknown> | ReadonlyArray<unknown>>(\n array: T,\n callback: (\n value: T extends Array<infer V> | ReadonlyArray<infer V> ? V : never,\n index: number,\n source: T\n ) => boolean | unknown\n): T;\nexport function each<T extends ArrayLike<unknown>>(\n arrayLikeObject: T,\n callback: (\n value: T extends ArrayLike<infer V> ? V : never,\n index: number,\n source: T\n ) => boolean | unknown\n): T;\nexport function each<T extends PlainObject>(\n obj: T,\n callback: (value: any, key: string, source: T) => boolean | unknown\n): T;\nexport function each(\n source: Array<unknown> | ArrayLike<unknown> | ReadonlyArray<unknown> | PlainObject,\n callback: (value: any, indexOrKey: any, source: any) => boolean | unknown\n): Array<unknown> | ArrayLike<unknown> | ReadonlyArray<unknown> | Set<unknown> | PlainObject {\n if (isArrayLike(source)) {\n for (let i = 0; i < source.length; i++) {\n if (callback(source[i], i, source) === false) {\n break;\n }\n }\n } else if (source) {\n // cant use support func keys here due to circular dep\n each(Object.keys(source), (key) => callback(source[key], key, source));\n }\n return source;\n}\n\n/**\n * Returns true when the passed item is in the passed array and false otherwise.\n * @param arr The array.\n * @param item The item.\n * @returns Whether the item is in the array.\n */\nexport const inArray = <T = any>(arr: T[] | readonly T[], item: T): boolean =>\n arr.indexOf(item) >= 0;\n\n/**\n * Concats two arrays and returns an new array without modifying any of the passed arrays.\n * @param a Array A.\n * @param b Array B.\n * @returns A new array which has the entries of both arrays.\n */\nexport const concat = <T>(a: T[] | ReadonlyArray<T>, b: T[] | ReadonlyArray<T>): T[] => a.concat(b);\n\n/**\n * Pushesh all given items into the given array and returns it.\n * @param array The array the items shall be pushed into.\n * @param items The items which shall be pushed into the array.\n */\nexport const push = <T>(array: T[], items: T | ArrayLike<T>, arrayIsSingleItem?: boolean): T[] => {\n if (!arrayIsSingleItem && !isString(items) && isArrayLike(items)) {\n Array.prototype.push.apply(array, items as T[]);\n } else {\n array.push(items as T);\n }\n return array;\n};\n\n/**\n * Creates a shallow-copied Array instance from an array-like or iterable object.\n * @param arr The object from which the array instance shall be created.\n */\nexport const from = <T = any>(arr?: ArrayLike<T> | Set<T>) => Array.from(arr || []);\n\n/**\n * Creates an array if the passed value is not an array, or returns the value if it is.\n * If the passed value is an array like structure and not a string it will be converted into an array.\n * @param value The value.\n * @returns An array which represents the passed value(s).\n */\nexport const createOrKeepArray = <T>(value: T | T[] | ArrayLike<T>): T[] => {\n if (isArray(value)) {\n return value;\n }\n return !isString(value) && isArrayLike(value) ? from(value) : [value];\n};\n\n/**\n * Check whether the passed array is empty.\n * @param array The array which shall be checked.\n */\nexport const isEmptyArray = (array: any[] | null | undefined): boolean => !!array && !array.length;\n\n/**\n * Deduplicates all items of the array.\n * @param array The array to be deduplicated.\n * @returns The deduplicated array.\n */\nexport const deduplicateArray = <T extends any[] | readonly any[]>(array: T): T =>\n from(new Set(array)) as T;\n\n/**\n * Calls all functions in the passed array/set of functions.\n * @param arr The array filled with function which shall be called.\n * @param args The args with which each function is called.\n * @param keep True when the Set / array should not be cleared afterwards, false otherwise.\n */\nexport const runEachAndClear = (arr: RunEachItem[], args?: any[], keep?: boolean): void => {\n // eslint-disable-next-line prefer-spread\n const runFn = (fn: RunEachItem) => (fn ? fn.apply(undefined, args || []) : true); // return true when fn is falsy to not break the loop\n each(arr, runFn);\n if (!keep) {\n (arr as any[]).length = 0;\n }\n};\n","export const strPaddingTop = 'paddingTop';\nexport const strPaddingRight = 'paddingRight';\nexport const strPaddingLeft = 'paddingLeft';\nexport const strPaddingBottom = 'paddingBottom';\nexport const strMarginLeft = 'marginLeft';\nexport const strMarginRight = 'marginRight';\nexport const strMarginBottom = 'marginBottom';\nexport const strOverflowX = 'overflowX';\nexport const strOverflowY = 'overflowY';\nexport const strWidth = 'width';\nexport const strHeight = 'height';\nexport const strVisible = 'visible';\nexport const strHidden = 'hidden';\nexport const strScroll = 'scroll';\n\nexport const capitalizeFirstLetter = (str: string | number | false | null | undefined): string => {\n const finalStr = String(str || '');\n return finalStr ? finalStr[0].toUpperCase() + finalStr.slice(1) : '';\n};\n","import type { WH } from '../dom/dimensions';\nimport type { XY } from '../dom/offset';\nimport type { TRBL } from '../dom/style';\nimport type { PlainObject } from '../../typings';\nimport { each } from './array';\nimport { mathRound } from './alias';\nimport { strHeight, strWidth } from './strings';\n\n/**\n * Compares two objects and returns true if all values of the passed prop names are identical, false otherwise or if one of the two object is falsy.\n * @param a Object a.\n * @param b Object b.\n * @param props The props which shall be compared.\n */\nexport const equal = <T extends PlainObject>(\n a: T | undefined,\n b: T | undefined,\n props: Array<keyof T> | ReadonlyArray<keyof T>,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n propMutation?: ((value: any) => any) | null | false\n): boolean => {\n if (a && b) {\n let result = true;\n each(props, (prop) => {\n const compareA = propMutation ? propMutation(a[prop]) : a[prop];\n const compareB = propMutation ? propMutation(b[prop]) : b[prop];\n if (compareA !== compareB) {\n result = false;\n }\n });\n return result;\n }\n return false;\n};\n\n/**\n * Compares object a with object b and returns true if both have the same property values, false otherwise.\n * Also returns false if one of the objects is undefined or null.\n * @param a Object a.\n * @param b Object b.\n */\nexport const equalWH = <T>(a?: Partial<WH<T>>, b?: Partial<WH<T>>) =>\n equal<Partial<WH<T>>>(a, b, ['w', 'h']);\n\n/**\n * Compares object a with object b and returns true if both have the same property values, false otherwise.\n * Also returns false if one of the objects is undefined or null.\n * @param a Object a.\n * @param b Object b.\n */\nexport const equalXY = <T>(a?: Partial<XY<T>>, b?: Partial<XY<T>>) =>\n equal<Partial<XY<T>>>(a, b, ['x', 'y']);\n\n/**\n * Compares object a with object b and returns true if both have the same property values, false otherwise.\n * Also returns false if one of the objects is undefined or null.\n * @param a Object a.\n * @param b Object b.\n */\nexport const equalTRBL = (a?: TRBL, b?: TRBL) => equal<TRBL>(a, b, ['t', 'r', 'b', 'l']);\n\n/**\n * Compares two DOM Rects for their equality of their width and height properties\n * Also returns false if one of the DOM Rects is undefined or null.\n * @param a DOM Rect a.\n * @param b DOM Rect b.\n * @param round Whether the values should be rounded.\n */\nexport const equalBCRWH = (a?: DOMRect, b?: DOMRect, round?: boolean) =>\n equal<DOMRect>(a, b, [strWidth, strHeight], round && ((value) => mathRound(value)));\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { isNumber, isFunction } from './types';\nimport { from } from './array';\nimport { rAF, cAF, setT, clearT } from './alias';\n\ntype DebouncerFn = (task: () => void) => () => void;\n\nexport type DebounceTiming = { _debouncer: DebouncerFn } | number | false | null | undefined;\nexport type DebounceLeading = boolean | null | undefined;\n\nexport interface DebounceOptions<FunctionToDebounce extends (...args: any) => any> {\n /**\n * The timing for debouncing. If false, null or undefined, no debounce is applied.\n */\n _debounceTiming?: DebounceTiming | (() => DebounceTiming);\n /**\n * The timing which determines when the debounced will be called even when the debounce timing did not call it yet.\n */\n _maxDebounceTiming?: DebounceTiming | (() => DebounceTiming);\n /**\n * Defines the calling on the leading edge of the timeout.\n */\n _leading?: DebounceLeading | (() => DebounceLeading);\n /**\n * Function which merges parameters for each canceled debounce.\n * If parameters can't be merged the function will return null, otherwise it returns the merged parameters.\n */\n _mergeParams?: (\n prev: Parameters<FunctionToDebounce>,\n curr: Parameters<FunctionToDebounce>\n ) => Parameters<FunctionToDebounce> | false | null | undefined;\n}\n\nexport interface Debounced<FunctionToDebounce extends (...args: any) => any> {\n (...args: Parameters<FunctionToDebounce>): ReturnType<FunctionToDebounce>;\n _flush(): void;\n}\n\nexport const bind = <A extends any[], B extends any[], R>(\n fn: (...args: [...A, ...B]) => R,\n ...args: A\n): ((...args: B) => R) => fn.bind(0, ...args);\n\n/**\n * Creates a timeout and cleartimeout tuple. The timeout function always clears the previously created timeout before it runs.\n * @param timeout The timeout in ms. If no timeout (or 0) is passed requestAnimationFrame is used instead of setTimeout.\n * @returns A tuple with the timeout function as the first value and the clearTimeout function as the second value.\n */\nexport const selfClearTimeout = (timeout?: number | (() => number)) => {\n let id: number;\n const setTFn = timeout ? setT : rAF!;\n const clearTFn = timeout ? clearT : cAF!;\n return [\n (callback: () => any) => {\n clearTFn(id);\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n id = setTFn(() => callback(), isFunction(timeout) ? timeout() : timeout);\n },\n () => clearTFn(id),\n ] as [timeout: (callback: () => any) => void, clear: () => void];\n};\n\nconst getDebouncer = (\n debounceTiming: DebounceTiming | (() => DebounceTiming)\n): DebouncerFn | false | null | undefined | void => {\n const debounceTimingResult = isFunction(debounceTiming) ? debounceTiming() : debounceTiming;\n if (isNumber(debounceTimingResult)) {\n const schedule = debounceTimingResult ? setT! : rAF!;\n const clear = debounceTimingResult ? clearT : cAF;\n return (task) => {\n const timeoutId = schedule!(\n () => task(),\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n debounceTimingResult\n );\n return () => {\n clear!(timeoutId);\n };\n };\n }\n\n return debounceTimingResult && debounceTimingResult._debouncer;\n};\n\n/**\n * Debounces the given function either with a timeout or a animation frame.\n * @param functionToDebounce The function which shall be debounced.\n * @param options Options for debouncing.\n */\nexport const debounce = <FunctionToDebounce extends (...args: any) => any>(\n functionToDebounce: FunctionToDebounce,\n options?: DebounceOptions<FunctionToDebounce>\n): Debounced<FunctionToDebounce> => {\n const {\n _debounceTiming: _timeout,\n _maxDebounceTiming: _maxDelay,\n _leading,\n _mergeParams,\n } = options || {};\n let cancelMaxTimeoutDebouncer: (() => void) | undefined;\n let cancelTimeoutDebounder: (() => void) | undefined;\n let prevArguments: Parameters<FunctionToDebounce> | null | undefined;\n let leadingInvoked: boolean | undefined;\n\n const invokeFunctionToDebounce = function (args: Parameters<FunctionToDebounce>) {\n if (cancelTimeoutDebounder) {\n cancelTimeoutDebounder();\n }\n if (cancelMaxTimeoutDebouncer) {\n cancelMaxTimeoutDebouncer();\n }\n\n leadingInvoked = cancelTimeoutDebounder = cancelMaxTimeoutDebouncer = prevArguments = undefined;\n // eslint-disable-next-line\n // @ts-ignore\n functionToDebounce.apply(this, args);\n };\n\n const mergeParms = (\n curr: Parameters<FunctionToDebounce>\n ): Parameters<FunctionToDebounce> | false | null | undefined =>\n _mergeParams && prevArguments ? _mergeParams(prevArguments, curr) : curr;\n\n const flush = () => {\n /* istanbul ignore next */\n if (cancelTimeoutDebounder && prevArguments) {\n invokeFunctionToDebounce(mergeParms(prevArguments) || prevArguments);\n }\n };\n\n const debouncedFn = function () {\n // eslint-disable-next-line prefer-rest-params\n const args: Parameters<FunctionToDebounce> = from(arguments) as Parameters<FunctionToDebounce>;\n const timeoutDebouncer = getDebouncer(_timeout);\n\n if (timeoutDebouncer) {\n const leading = typeof _leading === 'function' ? _leading() : _leading;\n const maxDelayDebouncer = getDebouncer(_maxDelay);\n const mergeParamsResult = mergeParms(args);\n const invokedArgs = mergeParamsResult || args;\n const boundInvoke = invokeFunctionToDebounce.bind(0, invokedArgs);\n\n if (cancelTimeoutDebounder) {\n cancelTimeoutDebounder();\n }\n\n if (leading && !leadingInvoked) {\n boundInvoke();\n leadingInvoked = true;\n cancelTimeoutDebounder = timeoutDebouncer(() => (leadingInvoked = undefined));\n } else {\n cancelTimeoutDebounder = timeoutDebouncer(boundInvoke);\n\n if (maxDelayDebouncer && !cancelMaxTimeoutDebouncer) {\n cancelMaxTimeoutDebouncer = maxDelayDebouncer(flush);\n }\n }\n\n prevArguments = invokedArgs;\n } else {\n invokeFunctionToDebounce(args);\n }\n };\n debouncedFn._flush = flush;\n\n return debouncedFn as Debounced<FunctionToDebounce>;\n};\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type { PlainObject } from '../../typings';\nimport { isArray, isFunction, isPlainObject, isNull } from './types';\nimport { each } from './array';\n\n/**\n * Determines whether the passed object has a property with the passed name.\n * @param obj The object.\n * @param prop The name of the property.\n */\nexport const hasOwnProperty = (obj: any, prop: string | number | symbol): boolean =>\n Object.prototype.hasOwnProperty.call(obj, prop);\n\n/**\n * Returns the names of the enumerable string properties and methods of an object.\n * @param obj The object of which the properties shall be returned.\n */\nexport const keys = (obj: any): Array<string> => (obj ? Object.keys(obj) : []);\n\ntype AssignDeep = {\n <T, U>(target: T, object1: U): T & U;\n <T, U, V>(target: T, object1: U, object2: V): T & U & V;\n <T, U, V, W>(target: T, object1: U, object2: V, object3: W): T & U & V & W;\n <T, U, V, W, X>(target: T, object1: U, object2: V, object3: W, object4: X): T & U & V & W & X;\n <T, U, V, W, X, Y>(\n target: T,\n object1: U,\n object2: V,\n object3: W,\n object4: X,\n object5: Y\n ): T & U & V & W & X & Y;\n <T, U, V, W, X, Y, Z>(\n target: T,\n object1?: U,\n object2?: V,\n object3?: W,\n object4?: X,\n object5?: Y,\n object6?: Z\n ): T & U & V & W & X & Y & Z;\n};\n\n// https://github.com/jquery/jquery/blob/master/src/core.js#L116\nexport const assignDeep: AssignDeep = <T, U, V, W, X, Y, Z>(\n target: T,\n object1?: U,\n object2?: V,\n object3?: W,\n object4?: X,\n object5?: Y,\n object6?: Z\n): T & U & V & W & X & Y & Z => {\n const sources: Array<any> = [object1, object2, object3, object4, object5, object6];\n\n // Handle case when target is a string or something (possible in deep copy)\n if ((typeof target !== 'object' || isNull(target)) && !isFunction(target)) {\n target = {} as T;\n }\n\n each(sources, (source) => {\n // Extend the base object\n each(source, (_, key) => {\n const copy: any = source[key];\n\n // Prevent Object.prototype pollution\n // Prevent never-ending loop\n if (target === copy) {\n return true;\n }\n\n const copyIsArray = isArray(copy);\n\n // Recurse if we're merging plain objects or arrays\n if (copy && isPlainObject(copy)) {\n const src = target[key as keyof T];\n let clone: any = src;\n\n // Ensure proper type for the source value\n if (copyIsArray && !isArray(src)) {\n clone = [];\n } else if (!copyIsArray && !isPlainObject(src)) {\n clone = {};\n }\n\n // Never move original objects, clone them\n target[key as keyof T] = assignDeep(clone, copy) as any;\n } else {\n target[key as keyof T] = copyIsArray ? copy.slice() : copy;\n }\n });\n });\n\n // Return the modified object\n return target as any;\n};\n\nexport const removeUndefinedProperties = <T extends PlainObject>(target: T, deep?: boolean): T =>\n each(assignDeep({}, target), (value, key, copy) => {\n if (value === undefined) {\n delete copy[key];\n } else if (deep && value && isPlainObject(value)) {\n copy[key as keyof typeof copy] = removeUndefinedProperties(value, deep) as any;\n }\n });\n\n/**\n * Returns true if the given object is empty, false otherwise.\n * @param obj The Object.\n */\nexport const isEmptyObject = (obj: any): boolean => !keys(obj).length;\n","export const noop = () => {};\n","import { mathMax, mathMin } from './alias';\n\n/**\n * Caps the passed number between the `min` and `max` bounds.\n * @param min The min bound.\n * @param max The max bound.\n * @param number The number to be capped.\n * @returns The capped number between min and max.\n */\nexport const capNumber = (min: number, max: number, number: number) =>\n mathMax(min, mathMin(max, number));\n","import type { HTMLElementTarget } from './types';\nimport { bind, deduplicateArray, each, from, isArray } from '../utils';\n\nexport type AttributeElementTarget = HTMLElementTarget | Element;\n\nexport type DomTokens = string | string[] | false | null | undefined | void;\n\nexport const getDomTokensArray = (tokens: DomTokens) =>\n deduplicateArray((isArray(tokens) ? tokens : (tokens || '').split(' ')).filter((token) => token));\n\n/**\n * Gets a attribute with the given attribute of the given element.\n * @param elm The element of which the attribute shall be get.\n * @param attrName The attribute name which shall be get.\n * @returns The attribute value or `null` when the attribute is not set or `false` if the element is undefined.\n */\nexport const getAttr = (elm: AttributeElementTarget, attrName: string) =>\n elm && elm.getAttribute(attrName);\n\n/**\n * Returns whether the given attribute exists on the given element.\n * @param elm The element.\n * @param attrName The attribute.\n * @returns A Truthy value indicates a present attrubte.\n */\nexport const hasAttr = (elm: AttributeElementTarget, attrName: string) =>\n elm && elm.hasAttribute(attrName);\n\n/**\n * Sets the given attributes to the given element.\n * @param elm The element of which the attributes shall be removed.\n * @param attrName The attribute names separated by a space.\n */\nexport const setAttrs = (\n elm: AttributeElementTarget,\n attrNames: string | string[],\n value: string | number | false | null | undefined\n) => {\n each(getDomTokensArray(attrNames), (attrName) => {\n if (elm) {\n elm.setAttribute(attrName, String(value || ''));\n }\n });\n};\n\n/**\n * Removes the given attributes from the given element.\n * @param elm The element of which the attribute shall be removed.\n * @param attrName The attribute names separated by a space.\n */\nexport const removeAttrs = (elm: AttributeElementTarget, attrNames: string | string[]): void => {\n each(getDomTokensArray(attrNames), (attrName) => elm && elm.removeAttribute(attrName));\n};\n\nexport const domTokenListAttr = (elm: AttributeElementTarget, attrName: string) => {\n const initialArr = getDomTokensArray(getAttr(elm, attrName));\n const setElmAttr = bind(setAttrs, elm, attrName);\n const domTokenListOperation = (operationTokens: DomTokens, operation: 'add' | 'delete') => {\n const initialArrSet = new Set(initialArr);\n each(getDomTokensArray(operationTokens), (token) => {\n initialArrSet[operation](token);\n });\n return from(initialArrSet).join(' ');\n };\n\n return {\n _remove: (removeTokens: DomTokens) => setElmAttr(domTokenListOperation(removeTokens, 'delete')),\n _add: (addTokens: DomTokens) => setElmAttr(domTokenListOperation(addTokens, 'add')),\n _has: (hasTokens: DomTokens) => {\n const tokenSet = getDomTokensArray(hasTokens);\n return tokenSet.reduce(\n (boolean, token) => boolean && initialArr.includes(token),\n tokenSet.length > 0\n );\n },\n };\n};\n\n/**\n * Treats the given attribute like the \"class\" attribute and removes the given value from it.\n * @param elm The element.\n * @param attrName The attributeName to which the value shall be removed.\n * @param value The value which shall be removed.\n */\nexport const removeAttrClass = (\n elm: AttributeElementTarget,\n attrName: string,\n value: DomTokens\n): (() => void) => {\n domTokenListAttr(elm, attrName)._remove(value);\n return bind(addAttrClass, elm, attrName, value);\n};\n\n/**\n * Treats the given attribute like the \"class\" attribute and adds value to it.\n * @param elm The element.\n * @param attrName The attributeName to which the value shall be added.\n * @param value The value which shall be added.\n */\nexport const addAttrClass = (\n elm: AttributeElementTarget,\n attrName: string,\n value: DomTokens\n): (() => void) => {\n domTokenListAttr(elm, attrName)._add(value);\n return bind(removeAttrClass, elm, attrName, value);\n};\n\nexport const addRemoveAttrClass = (\n elm: AttributeElementTarget,\n attrName: string,\n value: DomTokens,\n add?: boolean\n) => (add ? addAttrClass : removeAttrClass)(elm, attrName, value);\n\n/**\n * Treats the given attribute like the \"class\" attribute and checks if the given value is in it.\n * @param elm The element.\n * @param attrName The attributeName from which the content shall be checked.\n * @param value The value.\n * @returns True if the given attribute has the value in it, false otherwise.\n */\nexport const hasAttrClass = (\n elm: AttributeElementTarget,\n attrName: string,\n value: DomTokens\n): boolean => domTokenListAttr(elm, attrName)._has(value);\n","import type { AttributeElementTarget, DomTokens } from './attribute';\nimport { each, from } from '../utils/array';\nimport { bind } from '../utils/function';\nimport { domTokenListAttr } from './attribute';\n\nconst createDomTokenListClass = (elm: AttributeElementTarget) => domTokenListAttr(elm, 'class');\n\n/**\n * Check whether the given element has the given class name(s).\n * @param elm The element.\n * @param className The class name(s).\n */\nexport const hasClass = (elm: AttributeElementTarget, className: DomTokens): boolean =>\n createDomTokenListClass(elm)._has(className);\n\n/**\n * Removes the given class name(s) from the given element.\n * @param elm The element.\n * @param className The class name(s) which shall be removed. (separated by spaces)\n */\nexport const removeClass = (elm: AttributeElementTarget, className: DomTokens): void => {\n createDomTokenListClass(elm)._remove(className);\n};\n\n/**\n * Adds the given class name(s) to the given element.\n * @param elm The element.\n * @param className The class name(s) which shall be added. (separated by spaces)\n * @returns A function which removes the added class name(s).\n */\nexport const addClass = (elm: AttributeElementTarget, className: DomTokens): (() => void) => {\n createDomTokenListClass(elm)._add(className);\n return bind(removeClass, elm, className);\n};\n\n/**\n * Takes two className strings, compares them and returns the difference as array.\n * @param classNameA ClassName A.\n * @param classNameB ClassName B.\n */\nexport const diffClass = (\n classNameA: string | false | null | undefined,\n classNameB: string | false | null | undefined\n) => {\n const set = new Set<string>(classNameA ? classNameA.split(' ') : []);\n\n each(classNameB ? classNameB.split(' ') : [], (className) => {\n set[set.has(className) ? 'delete' : 'add'](className);\n });\n\n return from(set);\n};\n","import type { NodeElementTarget } from './types';\nimport { isElement } from '../utils/types';\nimport { push, from } from '../utils/array';\n\n/**\n * Find all elements with the passed selector, outgoing (and including) the passed element or the document if no element was provided.\n * @param selector The selector which has to be searched by.\n * @param elm The element from which the search shall be outgoing.\n */\nexport const find = (selector: string, elm?: NodeElementTarget): Element[] => {\n const rootElm = elm ? isElement(elm) && elm : document;\n return rootElm ? from(rootElm.querySelectorAll(selector)) : [];\n};\n\n/**\n * Find the first element with the passed selector, outgoing (and including) the passed element or the document if no element was provided.\n * @param selector The selector which has to be searched by.\n * @param elm The element from which the search shall be outgoing.\n */\nexport const findFirst = (selector: string, elm?: NodeElementTarget): NodeElementTarget => {\n const rootElm = elm ? isElement(elm) && elm : document;\n return rootElm && rootElm.querySelector(selector);\n};\n\n/**\n * Determines whether the passed element is matching with the passed selector.\n * @param elm The element which has to be compared with the passed selector.\n * @param selector The selector which has to be compared with the passed element. Additional selectors: ':visible' and ':hidden'.\n */\nexport const is = (elm: NodeElementTarget, selector: string): boolean =>\n isElement(elm) && elm.matches(selector);\n\nexport const isBodyElement = (elm: NodeElementTarget) => is(elm, 'body'); // don't do targetElement === ownerDocument.body in case initialization happens in memory\n\n/**\n * Returns the children (no text-nodes or comments) of the passed element which are matching the passed selector. An empty array is returned if the passed element is null.\n * @param elm The element of which the children shall be returned.\n * @param selector The selector which must match with the children elements.\n */\nexport const children = (elm: NodeElementTarget, selector?: string): ReadonlyArray<Element> => {\n const childs: Array<Element> = [];\n\n return isElement(elm)\n ? push(\n childs,\n from(elm.children).filter((child) => (selector ? is(child, selector) : child))\n )\n : childs;\n};\n\n/**\n * Returns the childNodes (incl. text-nodes or comments etc.) of the passed element. An empty array is returned if the passed element is null.\n * @param elm The element of which the childNodes shall be returned.\n */\nexport const contents = (elm: NodeElementTarget): ReadonlyArray<ChildNode> =>\n elm ? from(elm.childNodes) : [];\n\n/**\n * Returns the parent element of the passed element, or null if the passed element is null.\n * @param elm The element of which the parent element shall be returned.\n */\nexport const parent = (elm: NodeElementTarget): NodeElementTarget => elm && elm.parentElement;\n\n/**\n * Returns the closest element to the passed element which matches the given selector.\n * @param elm The element.\n * @param selector The selector.\n * @returns The closest element to the passed element which matches the given selector.\n */\nexport const closest = (elm: NodeElementTarget, selector: string): NodeElementTarget =>\n isElement(elm) && elm.closest(selector);\n\n/**\n * Gets the focused element of the passed or default document.\n * @returns The focused element of the passed document.\n */\nexport const getFocusedElement = (doc?: Document) => (doc || document).activeElement;\n\n/**\n * Determines whether the given element lies between two selectors in the DOM.\n * @param elm The element.\n * @param highBoundarySelector The high boundary selector.\n * @param deepBoundarySelector The deep boundary selector.\n */\nexport const liesBetween = (\n elm: NodeElementTarget,\n highBoundarySelector: string,\n deepBoundarySelector: string\n): boolean => {\n const closestHighBoundaryElm = closest(elm, highBoundarySelector);\n const closestDeepBoundaryElm = elm && findFirst(deepBoundarySelector, closestHighBoundaryElm);\n const deepBoundaryIsValid =\n closest(closestDeepBoundaryElm, highBoundarySelector) === closestHighBoundaryElm;\n\n return closestHighBoundaryElm && closestDeepBoundaryElm\n ? closestHighBoundaryElm === elm ||\n closestDeepBoundaryElm === elm ||\n (deepBoundaryIsValid &&\n closest(closest(elm, deepBoundarySelector), highBoundarySelector) !==\n closestHighBoundaryElm)\n : false;\n};\n","import type { NodeElementTarget, NodeElementTargetCollection } from './types';\nimport { createOrKeepArray, each } from '../utils/array';\nimport { parent } from './traversal';\nimport { bind } from '../utils';\n\n/**\n * Removes the given Nodes from their parent.\n * @param nodes The Nodes which shall be removed.\n */\nexport const removeElements = (nodes: NodeElementTargetCollection): void => {\n each(createOrKeepArray(nodes), (node) => {\n const parentElm = parent(node);\n if (node && parentElm) {\n parentElm.removeChild(node);\n }\n });\n};\n\n/**\n * Appends the given children at the end of the given Node.\n * @param node The Node to which the children shall be appended.\n * @param children The Nodes which shall be appended.\n * @returns A function which removes the inserted nodes.\n */\nexport const appendChildren = (node: NodeElementTarget, children: NodeElementTargetCollection) =>\n bind(\n removeElements,\n node &&\n children &&\n each(createOrKeepArray(children), (child) => {\n if (child) {\n node.appendChild(child);\n }\n })\n );\n","// at the time of implementation TypeScript doesn't offer any TrustedTypes typescript definitions\n// https://github.com/microsoft/TypeScript/issues/30024\nlet trustedTypePolicy: unknown | undefined;\n\nexport const getTrustedTypePolicy = () => trustedTypePolicy;\nexport const setTrustedTypePolicy = (newTrustedTypePolicy: unknown | undefined) => {\n trustedTypePolicy = newTrustedTypePolicy;\n};\n","import { each } from '../utils/array';\nimport { setAttrs } from './attribute';\nimport { contents } from './traversal';\nimport { removeElements } from './manipulation';\nimport { getTrustedTypePolicy } from '../../trustedTypePolicy';\n\n/**\n * Creates a div DOM node.\n */\nexport const createDiv = (classNames?: string): HTMLDivElement => {\n const div = document.createElement('div');\n setAttrs(div, 'class', classNames);\n return div;\n};\n\n/**\n * Creates DOM nodes modeled after the passed html string and returns the root dom nodes as a array.\n * @param html The html string after which the DOM nodes shall be created.\n */\nexport const createDOM = (html: string): ReadonlyArray<Node> => {\n const createdDiv = createDiv();\n const trustedTypesPolicy = getTrustedTypePolicy();\n const trimmedHtml = html.trim();\n createdDiv.innerHTML = trustedTypesPolicy\n ? // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (trustedTypesPolicy as any).createHTML(trimmedHtml)\n : trimmedHtml;\n\n return each(contents(createdDiv), (elm) => removeElements(elm));\n};\n","import type { PlainObject, StyleObject, StyleObjectKey, StyleObjectValue } from '../../typings';\nimport type { XY } from './offset';\nimport type { HTMLElementTarget } from './types';\nimport { wnd } from '../utils/alias';\nimport { each, from } from '../utils/array';\nimport { isString, isNumber, isObject, isNull, isBoolean } from '../utils/types';\n\nexport interface TRBL {\n t: number;\n r: number;\n b: number;\n l: number;\n}\n\nconst getCSSVal = (computedStyle: CSSStyleDeclaration, prop: StyleObjectKey): string =>\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n computedStyle.getPropertyValue(prop) || computedStyle[prop as any] || '';\n\nconst validFiniteNumber = (number: number) => {\n const notNaN = number || 0;\n return isFinite(notNaN) ? notNaN : 0;\n};\n\nconst parseToZeroOrNumber = (value?: string): number => validFiniteNumber(parseFloat(value || ''));\n\nexport const roundCssNumber = (value: number) => Math.round(value * 10000) / 10000;\n\nexport const ratioToCssPercent = (ratio: number) =>\n `${roundCssNumber(validFiniteNumber(ratio) * 100)}%`;\n\nexport const numberToCssPx = (number: number) => `${roundCssNumber(validFiniteNumber(number))}px`;\n\nexport function setStyles(\n elm: HTMLElementTarget,\n styles: StyleObject | false | null | undefined\n): void {\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n elm &&\n styles &&\n each(styles, (rawValue: StyleObjectValue, name) => {\n try {\n const elmStyle = elm.style;\n const value =\n isNull(rawValue) || isBoolean(rawValue)\n ? ''\n : isNumber(rawValue)\n ? numberToCssPx(rawValue)\n : rawValue;\n\n if (name.indexOf('--') === 0) {\n elmStyle.setProperty(name, value);\n } else {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n elmStyle[name as any] = value;\n }\n // eslint-disable-next-line no-empty\n } catch {}\n });\n}\n\nexport function getStyles(\n elm: HTMLElementTarget,\n styles: Array<StyleObjectKey> | ReadonlyArray<StyleObjectKey>,\n pseudoElm?: string | null | undefined\n): Partial<Record<StyleObjectKey, string>>;\nexport function getStyles(\n elm: HTMLElementTarget,\n styles: StyleObjectKey,\n pseudoElm?: string | null | undefined\n): string;\nexport function getStyles(\n elm: HTMLElementTarget,\n styles: Array<StyleObjectKey> | ReadonlyArray<StyleObjectKey> | StyleObjectKey,\n pseudoElm?: string | null | undefined\n): Partial<Record<StyleObjectKey, string>> | string {\n const getSingleStyle = isString(styles);\n let getStylesResult: string | PlainObject = getSingleStyle ? '' : {};\n\n if (elm) {\n const computedStyle = wnd.getComputedStyle(elm, pseudoElm) || elm.style;\n getStylesResult = getSingleStyle\n ? getCSSVal(computedStyle, styles)\n : from(styles).reduce((result, key) => {\n result[key] = getCSSVal(computedStyle, key);\n return result;\n }, getStylesResult as PlainObject);\n }\n return getStylesResult;\n}\n\n/**\n * Returns the top right bottom left values of the passed css property.\n * @param elm The element of which the values shall be returned.\n * @param propertyPrefix The css property prefix. (e.g. \"border\")\n * @param propertySuffix The css property suffix. (e.g. \"width\")\n */\nexport const topRightBottomLeft = (\n elm?: HTMLElementTarget,\n propertyPrefix?: string,\n propertySuffix?: string\n): TRBL => {\n const finalPrefix = propertyPrefix ? `${propertyPrefix}-` : '';\n const finalSuffix = propertySuffix ? `-${propertySuffix}` : '';\n const top = `${finalPrefix}top${finalSuffix}` as StyleObjectKey;\n const right = `${finalPrefix}right${finalSuffix}` as StyleObjectKey;\n const bottom = `${finalPrefix}bottom${finalSuffix}` as StyleObjectKey;\n const left = `${finalPrefix}left${finalSuffix}` as StyleObjectKey;\n const result = getStyles(elm, [top, right, bottom, left]);\n return {\n t: parseToZeroOrNumber(result[top]),\n r: parseToZeroOrNumber(result[right]),\n b: parseToZeroOrNumber(result[bottom]),\n l: parseToZeroOrNumber(result[left]),\n };\n};\n\nexport const getTrasformTranslateValue = (\n value: string | number | XY<string | number>,\n isHorizontal?: boolean\n) =>\n `translate${\n isObject(value) ? `(${value.x},${value.y})` : `${isHorizontal ? 'X' : 'Y'}(${value})`\n }`;\n","import type { HTMLElementTarget } from './types';\nimport { getStyles } from './style';\nimport { mathRound, wnd } from '../utils/alias';\nimport { bind } from '../utils/function';\nimport { strHeight, strWidth } from '../utils/strings';\n\nexport interface WH<T = number> {\n w: T;\n h: T;\n}\n\nconst elementHasDimensions = (elm: HTMLElement): boolean =>\n !!(elm.offsetWidth || elm.offsetHeight || elm.getClientRects().length);\nconst zeroObj: WH = {\n w: 0,\n h: 0,\n};\n\nconst getElmWidthHeightProperty = <E extends HTMLElement | Window>(\n property: E extends HTMLElement ? 'client' | 'offset' | 'scroll' : 'inner',\n elm: E | false | null | undefined\n): Readonly<WH> =>\n elm\n ? {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n w: (elm as any)[`${property}Width`],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n h: (elm as any)[`${property}Height`],\n }\n : zeroObj;\n\n/**\n * Returns the window inner- width and height.\n */\nexport const getWindowSize = (customWnd?: Window): Readonly<WH> =>\n getElmWidthHeightProperty('inner', customWnd || wnd);\n\n/**\n * Returns the scroll- width and height of the passed element. If the element is null the width and height values are 0.\n * @param elm The element of which the scroll- width and height shall be returned.\n */\nexport const getOffsetSize = bind(getElmWidthHeightProperty<HTMLElement>, 'offset') satisfies (\n elm: HTMLElementTarget\n) => Readonly<WH>;\n\n/**\n * Returns the client- width and height of the passed element. If the element is null the width and height values are 0.\n * @param elm The element of which the client- width and height shall be returned.\n */\nexport const getClientSize = bind(getElmWidthHeightProperty<HTMLElement>, 'client') satisfies (\n elm: HTMLElementTarget\n) => Readonly<WH>;\n\n/**\n * Returns the client- width and height of the passed element. If the element is null the width and height values are 0.\n * @param elm The element of which the client- width and height shall be returned.\n */\nexport const getScrollSize = bind(getElmWidthHeightProperty<HTMLElement>, 'scroll') satisfies (\n elm: HTMLElementTarget\n) => Readonly<WH>;\n\n/**\n * Returns the fractional- width and height of the passed element. If the element is null the width and height values are 0.\n * @param elm The element of which the fractional- width and height shall be returned.\n */\nexport const getFractionalSize = (elm: HTMLElementTarget): Readonly<WH> => {\n const cssWidth = parseFloat(getStyles(elm, strWidth)) || 0;\n const cssHeight = parseFloat(getStyles(elm, strHeight)) || 0;\n return {\n w: cssWidth - mathRound(cssWidth),\n h: cssHeight - mathRound(cssHeight),\n };\n};\n\n/**\n * Returns the BoundingClientRect of the passed element.\n * @param elm The element of which the BoundingClientRect shall be returned.\n */\nexport const getBoundingClientRect = (elm: HTMLElement): DOMRect => elm.getBoundingClientRect();\n\n/**\n * Determines whether the passed element has any dimensions.\n * @param elm The element.\n */\nexport const hasDimensions = (elm: HTMLElementTarget): boolean =>\n !!elm && elementHasDimensions(elm);\n\n/**\n * Determines whether the passed DOM Rect has any dimensions.\n */\nexport const domRectHasDimensions = (rect?: DOMRectReadOnly | false | null) =>\n !!(rect && (rect[strHeight] || rect[strWidth]));\n\n/**\n * Determines whether current DOM Rect has appeared according the the previous dom rect..\n * @param currContentRect The current DOM Rect.\n * @param prevContentRect The previous DOM Rect.\n * @returns Whether the dom rect appeared.\n */\nexport const domRectAppeared = (\n currContentRect: DOMRectReadOnly | false | null | undefined,\n prevContentRect: DOMRectReadOnly | false | null | undefined\n) => {\n const rectHasDimensions = domRectHasDimen