mirror of
https://github.com/tenrok/OverlayScrollbars.git
synced 2026-06-22 03:30:35 +03:00
wip
This commit is contained in:
@@ -26,10 +26,13 @@ interface AbstractLifecycle<O extends PlainObject> {
|
|||||||
|
|
||||||
export interface Lifecycle<T extends PlainObject> extends AbstractLifecycle<T> {
|
export interface Lifecycle<T extends PlainObject> extends AbstractLifecycle<T> {
|
||||||
_destruct(): void;
|
_destruct(): void;
|
||||||
|
_onSizeChanged?(): void;
|
||||||
|
_onDirectionChanged?(direction: 'ltr' | 'rtl'): void;
|
||||||
|
_onTrinsicChanged?(widthIntrinsic: boolean, heightIntrinsic: boolean): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LifecycleBase<O extends PlainObject, C extends PlainObject> extends AbstractLifecycle<O> {
|
export interface LifecycleBase<O extends PlainObject, C extends PlainObject> extends AbstractLifecycle<O> {
|
||||||
_cacheChange(cachePropsToUpdate?: CachePropsToUpdate<C>): void;
|
_updateCache(cachePropsToUpdate?: CachePropsToUpdate<C>): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -80,7 +83,7 @@ export const createLifecycleBase = <O, C>(
|
|||||||
_update: (force?: boolean) => {
|
_update: (force?: boolean) => {
|
||||||
update({ _force: !!force });
|
update({ _force: !!force });
|
||||||
},
|
},
|
||||||
_cacheChange: (cachePropsToUpdate?: CachePropsToUpdate<C>) => {
|
_updateCache: (cachePropsToUpdate?: CachePropsToUpdate<C>) => {
|
||||||
update({ _changedCache: cachePropsToUpdate });
|
update({ _changedCache: cachePropsToUpdate });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,21 +1,17 @@
|
|||||||
import {
|
import {
|
||||||
cssProperty,
|
cssProperty,
|
||||||
createDOM,
|
|
||||||
runEach,
|
runEach,
|
||||||
contents,
|
|
||||||
appendChildren,
|
|
||||||
removeElements,
|
|
||||||
addClass,
|
|
||||||
topRightBottomLeft,
|
topRightBottomLeft,
|
||||||
TRBL,
|
TRBL,
|
||||||
equalTRBL,
|
equalTRBL,
|
||||||
optionsTemplateTypes as oTypes,
|
optionsTemplateTypes as oTypes,
|
||||||
OptionsTemplateValue,
|
OptionsTemplateValue,
|
||||||
|
style,
|
||||||
|
hasOwnProperty,
|
||||||
} from 'support';
|
} from 'support';
|
||||||
|
import { OSTargetObject } from 'typings';
|
||||||
import { createLifecycleBase, Lifecycle } from 'lifecycles/lifecycleBase';
|
import { createLifecycleBase, Lifecycle } from 'lifecycles/lifecycleBase';
|
||||||
import { getEnvironment, Environment } from 'environment';
|
import { getEnvironment, Environment } from 'environment';
|
||||||
import { createSizeObserver } from 'observers/sizeObserver';
|
|
||||||
import { createTrinsicObserver } from 'observers/trinsicObserver';
|
|
||||||
|
|
||||||
export type OverflowBehavior = 'hidden' | 'scroll' | 'visible-hidden' | 'visible-scroll';
|
export type OverflowBehavior = 'hidden' | 'scroll' | 'visible-hidden' | 'visible-scroll';
|
||||||
export interface StructureLifecycleOptions {
|
export interface StructureLifecycleOptions {
|
||||||
@@ -39,7 +35,11 @@ const classNameViewportScrollbarStyling = `${classNameViewport}-scrollbar-styled
|
|||||||
const cssMarginEnd = cssProperty('margin-inline-end');
|
const cssMarginEnd = cssProperty('margin-inline-end');
|
||||||
const cssBorderEnd = cssProperty('border-inline-end');
|
const cssBorderEnd = cssProperty('border-inline-end');
|
||||||
|
|
||||||
export const createStructureLifecycle = (target: HTMLElement, initialOptions?: StructureLifecycleOptions): Lifecycle<StructureLifecycleOptions> => {
|
export const createStructureLifecycle = (
|
||||||
|
target: OSTargetObject,
|
||||||
|
initialOptions?: StructureLifecycleOptions
|
||||||
|
): Lifecycle<StructureLifecycleOptions> => {
|
||||||
|
const { host, viewport, content } = target;
|
||||||
const destructFns: (() => any)[] = [];
|
const destructFns: (() => any)[] = [];
|
||||||
const env: Environment = getEnvironment();
|
const env: Environment = getEnvironment();
|
||||||
const scrollbarsOverlaid = env._nativeScrollbarIsOverlaid;
|
const scrollbarsOverlaid = env._nativeScrollbarIsOverlaid;
|
||||||
@@ -48,10 +48,7 @@ export const createStructureLifecycle = (target: HTMLElement, initialOptions?: S
|
|||||||
// direction change is only needed to update scrollbar hiding, therefore its not needed if css can do it, scrollbars are invisible or overlaid on y axis
|
// direction change is only needed to update scrollbar hiding, therefore its not needed if css can do it, scrollbars are invisible or overlaid on y axis
|
||||||
const directionObserverObsolete = (cssMarginEnd && cssBorderEnd) || supportsScrollbarStyling || scrollbarsOverlaid.y;
|
const directionObserverObsolete = (cssMarginEnd && cssBorderEnd) || supportsScrollbarStyling || scrollbarsOverlaid.y;
|
||||||
|
|
||||||
const viewportElm = createDOM(`<div class="${classNameViewport} ${classNameViewportScrollbarStyling}"></div>`)[0];
|
const { _options, _update, _updateCache } = createLifecycleBase<StructureLifecycleOptions, StructureLifecycleCache>(
|
||||||
const contentElm = createDOM(`<div class="${classNameContent}"></div>`)[0];
|
|
||||||
|
|
||||||
const { _options, _update, _cacheChange } = createLifecycleBase<StructureLifecycleOptions, StructureLifecycleCache>(
|
|
||||||
{
|
{
|
||||||
paddingAbsolute: [false, oTypes.boolean],
|
paddingAbsolute: [false, oTypes.boolean],
|
||||||
overflowBehavior: {
|
overflowBehavior: {
|
||||||
@@ -60,37 +57,58 @@ export const createStructureLifecycle = (target: HTMLElement, initialOptions?: S
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
padding: [() => topRightBottomLeft(target, 'padding'), equalTRBL],
|
padding: [() => topRightBottomLeft(host, 'padding'), equalTRBL],
|
||||||
},
|
},
|
||||||
initialOptions,
|
initialOptions,
|
||||||
(changedOptions, changedCache) => {
|
(changedOptions, changedCache) => {
|
||||||
|
if (hasOwnProperty(changedOptions, 'paddingAbsolute') || hasOwnProperty(changedCache, 'padding')) {
|
||||||
|
const { padding } = changedCache;
|
||||||
|
const { paddingAbsolute } = changedOptions;
|
||||||
|
const paddingStyle: TRBL = {
|
||||||
|
t: 0,
|
||||||
|
r: 0,
|
||||||
|
b: 0,
|
||||||
|
l: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!paddingAbsolute) {
|
||||||
|
paddingStyle.t = -padding!.t;
|
||||||
|
paddingStyle.r = -(padding!.r + padding!.l);
|
||||||
|
paddingStyle.b = -(padding!.b + padding!.t);
|
||||||
|
paddingStyle.l = -padding!.l;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!supportsScrollbarStyling) {
|
||||||
|
paddingStyle.r -= env._nativeScrollbarSize.y;
|
||||||
|
paddingStyle.b -= env._nativeScrollbarSize.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
style(viewport, { top: paddingStyle.t, left: paddingStyle.l, 'margin-right': paddingStyle.r, 'margin-bottom': paddingStyle.b });
|
||||||
|
}
|
||||||
|
|
||||||
console.log(changedOptions); // eslint-disable-line
|
console.log(changedOptions); // eslint-disable-line
|
||||||
console.log(changedCache); // eslint-disable-line
|
console.log(changedCache); // eslint-disable-line
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// eslint-disable-next-line
|
const onSizeChanged = () => {
|
||||||
const onSizeChanged = (direction?: 'ltr' | 'rtl') => {
|
_updateCache('padding');
|
||||||
_cacheChange('padding');
|
|
||||||
};
|
};
|
||||||
const onTrinsicChanged = (widthIntrinsic: boolean, heightIntrinsic: boolean) => {
|
const onTrinsicChanged = (widthIntrinsic: boolean, heightIntrinsic: boolean) => {
|
||||||
console.log('heightAuot', heightIntrinsic); // eslint-disable-line
|
if (heightIntrinsic) {
|
||||||
|
style(content, { height: 'auto' });
|
||||||
|
} else {
|
||||||
|
style(content, { height: '100%' });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
appendChildren(viewportElm, contentElm);
|
|
||||||
appendChildren(contentElm, contents(target));
|
|
||||||
appendChildren(target, viewportElm);
|
|
||||||
addClass(target, classNameHost);
|
|
||||||
|
|
||||||
destructFns.push(createSizeObserver(target, onSizeChanged, { _appear: true, _direction: !directionObserverObsolete }));
|
|
||||||
destructFns.push(createTrinsicObserver(target, onTrinsicChanged));
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
_options,
|
_options,
|
||||||
_update,
|
_update,
|
||||||
|
_onSizeChanged: onSizeChanged,
|
||||||
|
_onTrinsicChanged: onTrinsicChanged,
|
||||||
_destruct() {
|
_destruct() {
|
||||||
runEach(destructFns);
|
runEach(destructFns);
|
||||||
removeElements(viewportElm);
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ export const createSizeObserver = (
|
|||||||
height: scrollAmount,
|
height: scrollAmount,
|
||||||
});
|
});
|
||||||
reset();
|
reset();
|
||||||
appearCallback = appear ? onScroll : reset;
|
appearCallback = appear ? () => onScroll() : reset;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (direction) {
|
if (direction) {
|
||||||
|
|||||||
@@ -1,54 +1,70 @@
|
|||||||
import { validateOptions, assignDeep } from 'support';
|
import { OSTarget, OSTargetObject } from 'typings';
|
||||||
import { Options, optionsTemplate } from 'options';
|
import { createStructureLifecycle } from 'lifecycles/structureLifecycle';
|
||||||
import { TargetElement } from 'overlayscrollbars';
|
import { appendChildren, addClass, contents, is, isHTMLElement, createDiv, each } from 'support';
|
||||||
import { Environment } from 'environment';
|
import { createSizeObserver } from 'observers/sizeObserver';
|
||||||
|
import { createTrinsicObserver } from 'observers/trinsicObserver';
|
||||||
|
import { Lifecycle } from 'lifecycles/lifecycleBase';
|
||||||
|
|
||||||
let ENVIRONMENT: Environment;
|
const classNameHost = 'os-host';
|
||||||
|
const classNameViewport = 'os-viewport';
|
||||||
|
const classNameContent = 'os-content';
|
||||||
|
|
||||||
interface UpdateHints {
|
const normalizeTarget = (target: OSTarget): OSTargetObject => {
|
||||||
_changedOptions: Options;
|
if (isHTMLElement(target)) {
|
||||||
}
|
const isTextarea = is(target, 'textarea');
|
||||||
|
const host = (isTextarea ? createDiv() : target) as HTMLElement;
|
||||||
|
const viewport = createDiv(classNameViewport);
|
||||||
|
const content = createDiv(classNameContent);
|
||||||
|
|
||||||
interface OverlayScrollbarsInstanceVars {
|
appendChildren(viewport, content);
|
||||||
_documentElm: Document;
|
appendChildren(content, contents(target));
|
||||||
_windowElm: Window;
|
appendChildren(target, viewport);
|
||||||
_htmlElm: HTMLElement;
|
addClass(host, classNameHost);
|
||||||
_bodyElm: HTMLElement;
|
|
||||||
_targetElm: TargetElement;
|
return {
|
||||||
_isTextarea: boolean;
|
target,
|
||||||
_isBody: boolean;
|
host,
|
||||||
_currentOptions: Options;
|
viewport,
|
||||||
_setOptions(newOptions: Options): Options;
|
content,
|
||||||
_update(updateHints: UpdateHints): void;
|
};
|
||||||
}
|
|
||||||
/*
|
|
||||||
const initSingletons = () => {
|
|
||||||
if (!ENVIRONMENT) {
|
|
||||||
ENVIRONMENT = new Environment();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { host, viewport, content } = target;
|
||||||
|
|
||||||
|
addClass(host, classNameHost);
|
||||||
|
addClass(viewport, classNameViewport);
|
||||||
|
addClass(content, classNameContent);
|
||||||
|
|
||||||
|
return target;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class OverlayScrollbars {
|
const OverlayScrollbars = (target: OSTarget, options?: any, extensions?: any): void => {
|
||||||
#instanceVars: OverlayScrollbarsInstanceVars = {
|
const osTarget: OSTargetObject = normalizeTarget(target);
|
||||||
_setOptions(newOptions: Options): Options {
|
const lifecycles: Lifecycle<any>[] = [];
|
||||||
const { _currentOptions } = this;
|
const { host } = osTarget;
|
||||||
const { _validated } = validateOptions(newOptions, optionsTemplate, _currentOptions, true);
|
|
||||||
|
|
||||||
this._currentOptions = assignDeep({}, _currentOptions, _validated);
|
lifecycles.push(createStructureLifecycle(osTarget));
|
||||||
|
|
||||||
return _validated;
|
// eslint-disable-next-line
|
||||||
},
|
const onSizeChanged = (direction?: 'ltr' | 'rtl') => {
|
||||||
|
if (direction) {
|
||||||
|
each(lifecycles, (lifecycle) => {
|
||||||
|
lifecycle._onDirectionChanged && lifecycle._onDirectionChanged(direction);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
each(lifecycles, (lifecycle) => {
|
||||||
|
lifecycle._onSizeChanged && lifecycle._onSizeChanged();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const onTrinsicChanged = (widthIntrinsic: boolean, heightIntrinsic: boolean) => {
|
||||||
|
each(lifecycles, (lifecycle) => {
|
||||||
|
lifecycle._onTrinsicChanged && lifecycle._onTrinsicChanged(widthIntrinsic, heightIntrinsic);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(target: HTMLElement, options: Options) {
|
createSizeObserver(host, onSizeChanged, { _appear: true, _direction: true });
|
||||||
this.#instanceVars._documentElm = document;
|
createTrinsicObserver(host, onTrinsicChanged);
|
||||||
this.#instanceVars._windowElm = window;
|
};
|
||||||
this.#instanceVars._htmlElm = document.body;
|
|
||||||
this.#instanceVars._bodyElm = document.body;
|
export { OverlayScrollbars };
|
||||||
this.#instanceVars._targetElm = document.body;
|
|
||||||
this.#instanceVars._isTextarea = false;
|
|
||||||
this.#instanceVars._isBody = false;
|
|
||||||
initSingletons();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
import { each } from 'support/utils/array';
|
import { each } from 'support/utils/array';
|
||||||
|
import { attr } from 'support/dom/attribute';
|
||||||
import { contents } from 'support/dom/traversal';
|
import { contents } from 'support/dom/traversal';
|
||||||
import { removeElements } from 'support/dom/manipulation';
|
import { removeElements } from 'support/dom/manipulation';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a div DOM node.
|
* Creates a div DOM node.
|
||||||
*/
|
*/
|
||||||
export const createDiv = (): HTMLDivElement => document.createElement('div');
|
export const createDiv = (classNames?: string): HTMLDivElement => {
|
||||||
|
const div = document.createElement('div');
|
||||||
|
if (classNames) {
|
||||||
|
attr(div, 'class', classNames);
|
||||||
|
}
|
||||||
|
return div;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates DOM nodes modeled after the passed html string and returns the root dom nodes as a array.
|
* Creates DOM nodes modeled after the passed html string and returns the root dom nodes as a array.
|
||||||
|
|||||||
@@ -95,10 +95,10 @@ export const show = (elm: HTMLElement | null): void => {
|
|||||||
*/
|
*/
|
||||||
export const topRightBottomLeft = (elm: HTMLElement | null, property?: string): TRBL => {
|
export const topRightBottomLeft = (elm: HTMLElement | null, property?: string): TRBL => {
|
||||||
const finalProp = property || '';
|
const finalProp = property || '';
|
||||||
const top = `${finalProp}Top`;
|
const top = `${finalProp}-top`;
|
||||||
const right = `${finalProp}Right`;
|
const right = `${finalProp}-right`;
|
||||||
const bottom = `${finalProp}Bottom`;
|
const bottom = `${finalProp}-bottom`;
|
||||||
const left = `${finalProp}Left`;
|
const left = `${finalProp}-left`;
|
||||||
const result = style(elm, [top, right, bottom, left]);
|
const result = style(elm, [top, right, bottom, left]);
|
||||||
return {
|
return {
|
||||||
t: parseToZeroOrNumber(result[top]),
|
t: parseToZeroOrNumber(result[top]),
|
||||||
|
|||||||
@@ -1,5 +1,15 @@
|
|||||||
import { each, from } from 'support/utils/array';
|
import { each, from } from 'support/utils/array';
|
||||||
|
|
||||||
|
const matches = (elm: Element | null, selector: string): boolean => {
|
||||||
|
if (elm) {
|
||||||
|
// eslint-disable-next-line
|
||||||
|
// @ts-ignore
|
||||||
|
const fn = Element.prototype.matches || Element.prototype.msMatchesSelector;
|
||||||
|
return fn.call(elm, selector);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find all elements with the passed selector, outgoing (and including) the passed element or the document if no element was provided.
|
* Find all elements with the passed selector, outgoing (and including) the passed element or the document if no element was provided.
|
||||||
* @param selector The selector which has to be searched by.
|
* @param selector The selector which has to be searched by.
|
||||||
@@ -27,7 +37,7 @@ export const findFirst = (selector: string, elm?: Element | null): Element | nul
|
|||||||
* @param elm The element which has to be compared with the passed selector.
|
* @param elm The element which has to be compared with the passed selector.
|
||||||
* @param selector The selector which has to be compared with the passed element. Additional selectors: ':visible' and ':hidden'.
|
* @param selector The selector which has to be compared with the passed element. Additional selectors: ':visible' and ':hidden'.
|
||||||
*/
|
*/
|
||||||
export const is = (elm: Element | null, selector: string): boolean => (elm ? elm.matches(selector) : false);
|
export const is = (elm: Element | null, selector: string): boolean => matches(elm, selector);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
* 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.
|
||||||
@@ -39,7 +49,7 @@ export const children = (elm: Element | null, selector?: string): ReadonlyArray<
|
|||||||
|
|
||||||
each(elm && elm.children, (child: Element) => {
|
each(elm && elm.children, (child: Element) => {
|
||||||
if (selector) {
|
if (selector) {
|
||||||
if (child.matches(selector)) {
|
if (matches(child, selector)) {
|
||||||
childs.push(child);
|
childs.push(child);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,5 +1,16 @@
|
|||||||
export type PlainObject<T = any> = { [name: string]: T };
|
export type PlainObject<T = any> = { [name: string]: T };
|
||||||
|
|
||||||
|
export type OSTargetElement = HTMLElement | HTMLTextAreaElement;
|
||||||
|
|
||||||
|
export interface OSTargetObject {
|
||||||
|
target: OSTargetElement;
|
||||||
|
host: HTMLElement;
|
||||||
|
viewport: HTMLElement;
|
||||||
|
content: HTMLElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type OSTarget = OSTargetElement | OSTargetObject;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
export namespace OverlayScrollbars {
|
export namespace OverlayScrollbars {
|
||||||
export type ResizeBehavior = 'none' | 'both' | 'horizontal' | 'vertical';
|
export type ResizeBehavior = 'none' | 'both' | 'horizontal' | 'vertical';
|
||||||
|
|||||||
@@ -102,29 +102,29 @@ describe('lifecycleBase', () => {
|
|||||||
describe('cache', () => {
|
describe('cache', () => {
|
||||||
test('single value cache change', () => {
|
test('single value cache change', () => {
|
||||||
const updateFn = jest.fn();
|
const updateFn = jest.fn();
|
||||||
const { _cacheChange } = createLifecycle({}, updateFn);
|
const { _updateCache } = createLifecycle({}, updateFn);
|
||||||
|
|
||||||
_cacheChange('number');
|
_updateCache('number');
|
||||||
expect(updateFn).toBeCalledTimes(2);
|
expect(updateFn).toBeCalledTimes(2);
|
||||||
expect(updateFn).toBeCalledWith({}, { number: 2 });
|
expect(updateFn).toBeCalledWith({}, { number: 2 });
|
||||||
|
|
||||||
_cacheChange('constant');
|
_updateCache('constant');
|
||||||
expect(updateFn).toBeCalledTimes(2);
|
expect(updateFn).toBeCalledTimes(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('multiple value cache change', () => {
|
test('multiple value cache change', () => {
|
||||||
const updateFn = jest.fn();
|
const updateFn = jest.fn();
|
||||||
const { _cacheChange } = createLifecycle({}, updateFn);
|
const { _updateCache } = createLifecycle({}, updateFn);
|
||||||
|
|
||||||
_cacheChange(['number', 'object']);
|
_updateCache(['number', 'object']);
|
||||||
expect(updateFn).toBeCalledTimes(2);
|
expect(updateFn).toBeCalledTimes(2);
|
||||||
expect(updateFn).toBeCalledWith({}, { number: 2, object: { string: 'hihi', boolean: false } });
|
expect(updateFn).toBeCalledWith({}, { number: 2, object: { string: 'hihi', boolean: false } });
|
||||||
|
|
||||||
_cacheChange(['number', 'constant']);
|
_updateCache(['number', 'constant']);
|
||||||
expect(updateFn).toBeCalledTimes(3);
|
expect(updateFn).toBeCalledTimes(3);
|
||||||
expect(updateFn).toBeCalledWith({}, { number: 3 });
|
expect(updateFn).toBeCalledWith({}, { number: 3 });
|
||||||
|
|
||||||
_cacheChange(['constant']);
|
_updateCache(['constant']);
|
||||||
expect(updateFn).toBeCalledTimes(3);
|
expect(updateFn).toBeCalledTimes(3);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -173,17 +173,17 @@ describe('lifecycleBase', () => {
|
|||||||
|
|
||||||
test('updates correctly on cache change', () => {
|
test('updates correctly on cache change', () => {
|
||||||
const updateFn = jest.fn();
|
const updateFn = jest.fn();
|
||||||
const { _cacheChange } = createLifecycle({}, updateFn);
|
const { _updateCache } = createLifecycle({}, updateFn);
|
||||||
|
|
||||||
_cacheChange('number');
|
_updateCache('number');
|
||||||
expect(updateFn).toBeCalledTimes(2);
|
expect(updateFn).toBeCalledTimes(2);
|
||||||
expect(updateFn).toBeCalledWith({}, { number: 2 });
|
expect(updateFn).toBeCalledWith({}, { number: 2 });
|
||||||
|
|
||||||
_cacheChange(['number', 'object', 'constant']);
|
_updateCache(['number', 'object', 'constant']);
|
||||||
expect(updateFn).toBeCalledTimes(3);
|
expect(updateFn).toBeCalledTimes(3);
|
||||||
expect(updateFn).toBeCalledWith({}, { number: 3, object: { string: 'hihi', boolean: false } });
|
expect(updateFn).toBeCalledWith({}, { number: 3, object: { string: 'hihi', boolean: false } });
|
||||||
|
|
||||||
_cacheChange('constant');
|
_updateCache('constant');
|
||||||
expect(updateFn).toBeCalledTimes(3);
|
expect(updateFn).toBeCalledTimes(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,11 @@ describe('dom create', () => {
|
|||||||
const createdDiv = createDiv();
|
const createdDiv = createDiv();
|
||||||
expect(createdDiv.parentElement).toBe(null);
|
expect(createdDiv.parentElement).toBe(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('with class names', () => {
|
||||||
|
const createdDiv = createDiv('a b c');
|
||||||
|
expect(createdDiv.classList.length).toBe(3);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('createDOM', () => {
|
describe('createDOM', () => {
|
||||||
|
|||||||
+2
-3
@@ -1,7 +1,6 @@
|
|||||||
import 'overlayscrollbars.scss';
|
import 'overlayscrollbars.scss';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
import { createStructureLifecycle } from 'lifecycles/structureLifecycle';
|
import { OverlayScrollbars } from 'overlayscrollbars/OverlayScrollbars';
|
||||||
|
|
||||||
const targetElm = document.querySelector('#target') as HTMLElement;
|
const targetElm = document.querySelector('#target') as HTMLElement;
|
||||||
|
OverlayScrollbars(targetElm);
|
||||||
const structureLifecycle = createStructureLifecycle(targetElm);
|
|
||||||
|
|||||||
@@ -137,6 +137,11 @@ const iterateDirection = async (afterEach?: () => any) => {
|
|||||||
const start = async () => {
|
const start = async () => {
|
||||||
setTestResult(null);
|
setTestResult(null);
|
||||||
|
|
||||||
|
console.log('init direction changes:', directionIterations);
|
||||||
|
console.log('init size changes:', sizeIterations);
|
||||||
|
should.ok(directionIterations > 0);
|
||||||
|
should.ok(sizeIterations > 0);
|
||||||
|
|
||||||
targetElm?.removeAttribute('style');
|
targetElm?.removeAttribute('style');
|
||||||
await iterateDisplay();
|
await iterateDisplay();
|
||||||
await iterateDirection();
|
await iterateDirection();
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ const rollupConfigDefaults = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const legacyBabelConfig = {
|
const legacyBabelConfig = {
|
||||||
exclude: isTestEnv ? [/\/core-js\//, /\/@testing-library\//] : [],
|
exclude: isTestEnv ? [/\/core-js\//] : [], // /\/@testing-library\//
|
||||||
presets: [
|
presets: [
|
||||||
[
|
[
|
||||||
'@babel/preset-env',
|
'@babel/preset-env',
|
||||||
|
|||||||
Reference in New Issue
Block a user